abc233


这场比赛编号是 233,好玩好玩

D - Count Interval

给出 \(n\) 个数,求有多少个连续段的和为 \(K\).

即求出 \((l,r)\) 的个数,\((l,r)\) 满足

\(1. 1\leq l\leq r\leq n\)

\(2. \sum\limits_{i=l}^{r} a_i=K\)

\(1\leq n\leq 2\cdot 10^5,\ |a_i|\leq 10^9,\ |K|\leq 10^{15}\)

考虑 \(\sum\limits_{i=l}^{r} a_i=\sum\limits_{i=1}^{r} a_i-\sum\limits_{i=1}^{l-1} a_i\) .

考虑用 \(\mathrm{map}\) 维护前缀和的数的数量即可.

时间复杂度 : \(O(n\log n)\)

空间复杂度 : \(O(n)\)

code
#include
using namespace std;
const int N=2e5+10;
int n;
long long k;
long long a[N];
mapcnt;
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n>>k;
    for(int i=0;i>a[i];
    for(int i=1;i

E - Σ[k=0..10100]floor(X/10k)

\(\sum\limits_{k=0}^{10^{100}}\lfloor \frac{X}{10^k}\rfloor\) .

\(1\leq X\leq 10^{500000}\)

这个式子相当于每次把这个数的最后一位删掉,得到 \(|X|\) 个数,然后把这些数相加.

这样肯定会 ttt,考虑答案中的第 \(i\) 位是原数位数中不大于 \(i\) 的所有加起来.

不能忘记考虑进位.

时间复杂度 : \(O(n)\)

空间复杂度 : \(O(n)\)

code
#include
using namespace std;
const int N=2e5+10;
int n;
long long k;
long long a[N];
mapcnt;
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n>>k;
    for(int i=0;i>a[i];
    for(int i=1;i

F - Swap and Sort

给出一个长度为 \(n\) 的排列 \(P\) .

给出 \(m\) 种操作. 第 \(i\) 种操作交换 \(P\) 中的第 \(a_i\) 个和第 \(b_i\) 个.

求是否能在不多于 \(5\cdot 10^5\) 次操作后排列有序.

如果能,给出方案.

\(1\leq n\leq 1000,1\leq m\leq \min(5\cdot 10^5,\frac{n(n-1}{2})\)

考虑 \(a_i\)\(b_i\) 连边构图.

如果存在 \(i\)\(P_i\) 不连通,那么肯定没有解.

对于一个连通块,保留一棵生成树就可以做到所有点都回到原本的位置上.

但是对于生成树的点操作的顺序是有讲究的. 考虑剥叶子,让位于叶子节点处的节点先通过操作回到原本的位置,然后再删掉这个节点.

操作方案即为 \(i\)\(P_i\) 上的边依次 swap.

时间复杂度 : \(O(n^2)\)

空间复杂度 : \(O(n+m)\)

code ```cpp #include #define MP make_pair #define FI first #define SE second using namespace std; const int N=1010; int n,m; int a[N]; int fa[N]; vector<><>,int> >e; vector<> >g[N]; bool vis[N]; vectorarr; int pos[N]; vectorop; vectorans; inline int get_fa(int x){return fa[x]==x?x:fa[x]=get_fa(fa[x]);} void work_tree(){ for(int i=0;i>n; for(int i=0;i>a[i],a[i]--; cin>>m; for(int i=0;i>u>>v; u--;v--; e.push_back(MP(MP(u,v),i)); } work_tree(); for(int i=0;i
#### G - Strongest Takahashi > 给出一个 $n\times n$ 的格子. 每个格子为 `.` 或 `#` . > > 每次可以选出其中一个 $d\times d$, 花费 $d$ 的代价将其全部覆盖为 `.` > > 问将全部格子覆盖成 `.` 的代价. > > $1\leq n\leq 50$ 考虑 $dp(x_1,y_1,x_2,y_2)$ 表示左上角为 $(x_1,y_1)$ 右下角为 $(x_2,y_2)$ 的矩形覆盖为 `.` 的最小代价. 转移的时间枚举横着切和纵着切的位置,合并取 $\min$ 即可. 时间复杂度 : $O(n^5)$ 空间复杂度 : $O(n^4)$
code ```c++ #include using namespace std; const int N=52; const int INF=0x3f3f3f3f; const int inf=1061109567; int n; char board[N][N]; bool ok[N][N][N][N]; int dp[N][N][N][N]; int dfs(int x1,int y1,int x2,int y2){ if(dp[x1][y1][x2][y2]!=inf)return dp[x1][y1][x2][y2]; if(x1==x2&&y1==y2)return dp[x1][y1][x2][y2]=ok[x1][y1][x2][y2]?0:1; int&res=dp[x1][y1][x2][y2]; for(int x3=x1;x3>n; for(int i=0;i>board[i][j]; for(int i=0;i <>
21
.....................
.....................
...#.#...............
....#.............#..
...#.#...........#.#.
..................#..
.....................
.....................
.....................
..........#.....#....
......#..###.........
........#####..#.....
.......#######.......
.....#..#####........
.......#######.......
......#########......
.......#######..#....
......#########......
..#..###########.....
.........###.........
.........###.........

haha, Merry Christmas and Happy New Year !

Ex - Manhattan Christmas Tree

给出 \(n\) 棵圣诞树的位置. 给出 \(q\) 个询问.

每个询问问距离 \((x,y)\) 位置曼哈顿距离最近的第 \(k\) 个点.

\(1\leq n\leq 10^5,\ 1\leq q\leq 10^5,\ 0\leq x,y\leq 10^5,\) 圣诞树的坐标不相同.

考虑二分距离 \(d\) , 如果是曼哈顿距离,那么构成的图形是一个斜着的矩形,求这个范围内的点是不好求的.

此时,有一个 trick,就是把切比雪夫转化,相当于逆时针旋转 \(45\) 度之后坐标乘上 \(\sqrt 2\). 在曼哈顿距离下为 \((x,y)\) 的坐标会变成 \((x-y,x+y)\). 但是此时距离当前询问的点小于等于距离为 \(d\) 的位置是一个正方形. 这就非常惹人喜爱.

看到 \(x,y\)\(0\)\(10^5\) 之内,所以切比雪夫之后,\(x,y\)\(-10^5\)\(2\cdot 10^5\) 之内.

考虑建立主席树,线段树上维护横坐标,每次加入一行,多次单点修改,维护新的根节点.

查询的时候只需要区间询问两次做一个差即可.

时间复杂度 : \(O(n\log^2 x)\)

空间复杂度 : \(o(n\log n)\)

code ```cpp #include using namespace std; char in[100010]; int iiter=0,llen=0; inline char get(){ if(iiter==llen)llen=fread(in,1,100000,stdin),iiter=0; if(llen==0)return EOF; return in[iiter++]; } inline int rd(){ char ch=getchar(); while(ch<'0'||ch>'9')ch=get(); int res=0; while(ch>='0'&&ch<='9'){ res=(res<<1)+(res<<3)+ch-'0'; ch=get(); } return res; } inline void pr(int res){ if(res==0){ putchar('0'); return; } static int out[10]; int len=0; while(res){ out[len++]=res%10; res/=10; } for(int i=len-1;i>=0;i--)putchar(out[i]+'0'); } const int N=1e5+10; const int M=2e5+10,P=1e5+3; const int K=4e7+10; class presi_tree{ public: int ts[K],ls[K],rs[K],rt[M],cnt=0; int build(int l,int r){ int x=++cnt; if(l==r){ ts[x]=0; return x; } int mid=(l+r)>>1; ls[x]=build(l,mid); rs[x]=build(mid+1,r); ts[x]=ts[ls[x]]+ts[rs[x]]; return x; } int upd(int pre,int l,int r,int pos){ int cur=++cnt; if(l==r){ ts[cur]=ts[pre]+1; return cur; } ls[cur]=ls[pre];rs[cur]=rs[pre]; int mid=(l+r)>>1; if(pos<=mid)ls[cur]=upd(ls[pre],l,mid,pos); else rs[cur]=upd(rs[pre],mid+1,r,pos); ts[cur]=ts[ls[cur]]+ts[rs[cur]]; return cur; } int qry(int x,int l,int r,int cl,int cr){ if(l==cl&&r==cr)return ts[x]; int mid=(l+r)>>1; if(cr<=mid)return qry(ls[x],l,mid,cl,cr); else if(mid+1<=cl)return qry(rs[x],mid+1,r,cl,cr); else return qry(ls[x],l,mid,cl,mid)+qry(rs[x],mid+1,r,mid+1,cr); } }T; int sum(int x,int y,int k){ return T.qry(T.rt[min(M-1,x+k)],0,M-1,max(y-k,0),min(y+k,M-1))- T.qry(T.rt[max(0,x-k-1)],0,M-1,max(y-k,0),min(y+k,M-1)); } void solve(){ int xx,yy,k; cin>>xx>>yy>>k; int x=xx-yy+P,y=xx+yy; int low=0,high=M+1,ans=M; while(low>1; if(sum(x,y,mid)>=k){ ans=min(ans,mid); high=mid; }else{ low=mid+1; } } cout6)  评论(0)  编辑  刷新页面返回顶部 Copyright ? 2022 xyangh
Powered by .NET 6 on Kubernetes