Solution
md,摆了一周,现在是彻底废了/kk
可以看出的是这玩意是若干个个环,不过我们会发现,这个性质没有什么用。
发现不好做,考虑操作分块。我们可以发现对于操作 \(1\) 我们现在就可以在操作 \(2\) 的时候考虑其产生的贡献。发现棘手的地方在于操作 \(3\) 直接改变了图的形状,所以似乎我们只能暴力。但是,我们发现很多点都是一起操作的,我们完全可以缩点。仔细观察可以发现,其实我们把 \(2,3\) 操作涉及到的点设为关键点,一个点染色为环上面它后面最近的关键点,那么同一颜色显然可以一起操作。又因为只有 \(sqrt n\) 个关键点,所以直接暴力就是 \(\Theta(n\sqrt n)\)。
当然了,在知道是操作分块后还不会做的我自然是个nc。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define int long long
#define MAXN 200005
#define MAXM 1305
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
bool vis[MAXN];
int n,m,cnt,tot,a[MAXN],b[MAXN],p[MAXN],sum[MAXN],ind[MAXN],pre[MAXN],col[MAXN],add[MAXN],siz[MAXM][MAXM];
void color (int x,int y){while (!col[x]) col[x] = y,x = pre[x];}
void addit (int x,int y){while (!vis[x]) add[x] += y,vis[x] = 1,x = col[p[x]];while (vis[x]) vis[x] = 0,x = col[p[x]];}
struct node{
int opt,x,y;
}seq[MAXN];
signed main(){
read (n);
for (Int x = 1;x <= n;++ x) read (a[x]);
for (Int x = 1;x <= n;++ x) read (p[x]),pre[p[x]] = x;
read (m);int Siz = sqrt (m);
for (Int L = 1;L <= m;L += Siz){
int R = min (m,L + Siz - 1);
cnt = tot = 0,memset (ind,0,sizeof (ind)),memset (add,0,sizeof (add)),memset (col,0,sizeof (col));
for (Int x = 1;x <= n;++ x) sum[x] = sum[x - 1] + a[x];
for (Int t = L;t <= R;++ t){
read (seq[t].opt,seq[t].x,seq[t].y);
if (seq[t].opt == 1){
if (!ind[seq[t].x - 1]) ind[seq[t].x - 1] = ++ cnt;
if (!ind[seq[t].y]) ind[seq[t].y] = ++ cnt;
}
else if (seq[t].opt == 2) col[seq[t].x] = seq[t].x;
else col[seq[t].x] = seq[t].x,col[seq[t].y] = seq[t].y;
}
for (Int x = 1;x <= n;++ x) if (col[x] == x) b[++ tot] = x,col[x] = 0,color (x,x);
for (Int x = 0;x <= n;++ x){
if (x) add[col[x]] ++;
if (ind[x]) for (Int i = 1;i <= tot;++ i) siz[ind[x]][i] = add[b[i]];
}
memset (add,0,sizeof (add));
for (Int t = L;t <= R;++ t){
int opt = seq[t].opt,x = seq[t].x,y = seq[t].y;
if (opt == 1){
int ans = sum[y] - sum[x - 1];
for (Int i = 1;i <= tot;++ i) ans += add[b[i]] * (siz[ind[y]][i] - siz[ind[x - 1]][i]);
write (ans),putchar ('\n');
}
else if (opt == 2) addit (x,y);
else swap (p[x],p[y]),pre[p[x]] = x,pre[p[y]] = y;
}
for (Int x = 1;x <= n;++ x) a[x] += add[col[x]];
}
return 0;
}
标签:vis,int,void,read,Jumping,MAXN,Through,CF1588F,col
From: https://www.cnblogs.com/Dark-Romance/p/16906265.html