「题目背景」
小奇在家中的花园漫步时,总是会思考一些奇怪的问题。
「问题描述」
小奇的花园有n个温室,标号为1到n,温室以及以及温室间的双向道路形成一棵树。
每个温室都种植着一种花,随着季节的变换,温室里的花的种类也在不断发生着变化。
小奇想知道从温室x走到温室y的路径中(包括两个端点),第t种花出现的次数。
「输入格式」
第一行为两个整数n,q,表示温室的数目和操作的数目。
第二行有n个整数T1,T2…Tn其中Ti表示温室i中的花的种类。
接下来n-1行,每个两个整数x, y,表示温室x和y之间有一条双向道路。
接下来q行,表示q个操作,分别为以下两种形式之一:
• C x t 表示在温室x中的花的种类变为t。
• Q x y t 表示询问温室x走到温室y的路径中(包括两个端点),第t种花出现
的次数。
为了体现在线操作,输入数据中的每个操作的参数都进行了加密。记最后一次询问的答案为anslast(一开始设anslast为0),下次读入中的x,y,t均需要异或上anslast以得到真实值,在C/C++中异或为ˆ运算符,在pascal中为xor运算符。
「输出格式」
输出q行,每行一个正整数表示该次询问答案。
「样例输入」
5 8
10 20 30 40 50
1 2
1 3
3 4
3 5
Q 2 5 10
C 2 21
Q 3 4 21
C 6 22
Q 1 7 28
C 5 20
Q 2 5 20
Q 2 0 9
「样例输出」
1
2
0
3
1
「样例解释」
加密前的操作:
Q 2 5 10
C 3 20
Q 2 5 20
C 4 20
Q 3 5 30
C 5 20
Q 2 5 20
Q 1 3 10
「数据范围」
对于30%的数据,有n <= 1000, q <= 2000。
对于50%的数据,有n <= 10000, q <= 20000。
对于100%的数据,有n <= 100000, q <= 200000,0 <= T < 2^31。
←小奇
下面的题解都是自己的话:
50%
既然强制在线,那我们就在线模拟,没什么方法,就一步步地往上找LCA并统计答案然后输出就好啦~
考场上实在没办法AC拿50分也不吃亏。
100%
有一个转化很重要。
我们可以通过类似求树上两点路径长度 dis=dep[x]+dep[y]-dep[LCA]*2 的方法,用s[i]表示从根节点到此时的i点col颜色的出现次数。
所以每次在某个节点的某个颜色出现次数增加1时,它的整个子树的每个节点的s[i]都会增加1,那么从x到y某个颜色的出现次数显然就变成 s[x]+s[y]-s[LCA]*2+val[LCA]了
那这样题目要求的单点修改、区间查询就被我们变成子树修改、单点查询了。子树修改用DFS序来看其实也就是区间修改了,可以用线段树解决。
但是颜色种类那么多怎么办呢(而且数值还那么大)?
可以用map来维护颜色编号,用动态开点线段树的方式对每一种颜色维护一棵线段树。
做本题是参考了黄学长Hzwer的题解和程序,代码可能有相似之处,但线段树的操作绝对是我自己的风格。(求资瓷~)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 8 #define For(i,a,b)for(register int i=a;i<=b;++i) 9 #define Dwn(i,a,b)for(register int i=a;i>=b;--i) 10 #define Re register 11 #define Pn putchar(' ') 12 13 using namespace std; 14 15 const int N=1e5+5,Nr=1e7+5; 16 int head[N],nxt[N*2],v[N*2],cnt=1; 17 int f[N][21],dfx[N],dID=0,dep[N],sz[N]; 18 int rt[N*3],ls[Nr],rs[Nr],tag[Nr],tr[Nr],tID=0; 19 int n,m,x,y,T[N*3],cID=0,t,Q,ans=0; 20 map<int,int>mp; 21 inline void read(int &v){ 22 v=0; 23 char c=getchar(); 24 while(c<'0'||c>'9')c=getchar(); 25 while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar(); 26 } 27 void write(int x){ 28 if(x>9)write(x/10); 29 int xx=x%10; 30 putchar(xx+'0'); 31 } 32 void add(int ux,int vx){ 33 cnt++; 34 nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx; 35 cnt++; 36 nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux; 37 } 38 39 void DFS(int x,int fa){ 40 sz[x]=1; 41 dfx[x]=++dID; 42 for(Re int i=head[x];i;i=nxt[i]){ 43 int vv=v[i]; 44 if(vv==fa)continue; 45 dep[vv]=dep[x]+1; 46 f[vv][0]=x; 47 DFS(vv,x); 48 sz[x]+=sz[vv]; 49 } 50 } 51 52 int LCA(int x,int y){ 53 if(dep[x]<dep[y])swap(x,y); 54 Dwn(b,20,0)if(f[x][b]!=-1){ 55 if(dep[f[x][b]]>=dep[y])x=f[x][b]; 56 } 57 if(x==y)return x; 58 Dwn(b,20,0)if(f[x][b]!=-1&&f[y][b]!=-1&&f[x][b]!=f[y][b]){ 59 x=f[x][b]; y=f[y][b]; 60 } 61 return f[x][0]; 62 } 63 64 65 void pDown(int o,int l,int r){ 66 if(!tag[o]||l==r)return; 67 int tg=tag[o]; tag[o]=0; 68 if(!ls[o])ls[o]=++tID; 69 if(!rs[o])rs[o]=++tID; 70 tr[ls[o]]+=tg; tag[ls[o]]+=tg; 71 tr[rs[o]]+=tg; tag[rs[o]]+=tg; 72 } 73 74 void Ins(int &o,int l,int r,int lx,int rx,int dt){ 75 if(!o)o=++tID; 76 if(lx<=l&&rx>=r){ 77 tr[o]+=dt; tag[o]+=dt; 78 return; 79 } 80 pDown(o,l,r); 81 int m=(l+r)>>1; 82 if(lx<=m)Ins(ls[o],l,m,lx,rx,dt); 83 if(rx>m)Ins(rs[o],m+1,r,lx,rx,dt); 84 } 85 86 int Qry(int o,int l,int r,int px){ 87 if(!o)return 0; 88 if(l==r)return tr[o]; 89 pDown(o,l,r); 90 int m=(l+r)>>1; 91 if(px<=m)return Qry(ls[o],l,m,px); 92 else return Qry(rs[o],m+1,r,px); 93 } 94 95 96 int main(){ 97 freopen("garden.in","r",stdin); 98 freopen("garden.out","w",stdout); 99 read(n); read(Q); 100 For(i,1,n){ 101 read(t); 102 if(!mp[t])mp[t]=++cID; 103 T[i]=mp[t]; 104 } 105 For(i,1,n-1){ 106 read(x); read(y); 107 add(x,y); 108 } 109 110 memset(f,-1,sizeof(f)); 111 DFS(1,0); 112 For(b,1,20) For(i,1,n){ 113 if(f[i][b-1]==-1)continue; 114 f[i][b]=f[ f[i][b-1] ][b-1]; 115 } 116 117 For(i,1,n){ 118 int lx=dfx[i]; 119 int rx=dfx[i]+sz[i]-1; 120 Ins(rt[T[i]],1,n,lx,rx,1); 121 } 122 123 For(i,1,Q){ 124 125 char opt=getchar(); 126 while(opt!='C'&&opt!='Q')opt=getchar(); 127 if(opt=='C'){ 128 read(x); read(t); 129 x^=ans; t^=ans; 130 if(!mp[t])mp[t]=++cID; 131 t=mp[t]; 132 int lx=dfx[x],rx=dfx[x]+sz[x]-1; 133 134 Ins(rt[T[x]],1,n,lx,rx,-1); 135 Ins(rt[t],1,n,lx,rx,1); 136 T[x]=t; 137 } 138 if(opt=='Q'){ 139 read(x); read(y); read(t); 140 x^=ans; y^=ans; t^=ans; 141 if(!mp[t])mp[t]=++cID; 142 t=mp[t]; 143 int xy=LCA(x,y); 144 int fn; 145 fn=Qry(rt[t],1,n,dfx[x])+Qry(rt[t],1,n,dfx[y]); 146 fn-=Qry(rt[t],1,n,dfx[xy])*2; 147 if(T[xy]==t)fn++; 148 ans=fn; 149 write(fn); Pn; 150 } 151 } 152 fclose(stdin); fclose(stdout); 153 return 0; 154 }