codechef FIBTREE 码农题 线段树 树剖 标记永久化
Posted 汪立超
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codechef FIBTREE 码农题 线段树 树剖 标记永久化相关的知识,希望对你有一定的参考价值。
好烦啊,调了半天
线段树部分标记比较多,手抖打错了一个
剩下的都是取模的问题
我自己瞎jb推的公式里保留了abs,但是在模意义下是gg的,所以必须把正负区分开
调试的时候一定要注意构造各种形状的树,不要只做随机树
随机树深度只有log,很难体现一些链上的性质
我用随机树拍了一下午没出错,一掏出直链就秒秒钟出错
最后找到了那个该死的abs
还是逻辑不够严谨啊
1 #include <bits/stdc++.h> 2 #define DEBUG 0 3 #define mid (l+r>>1) 4 #define MOD 1000000009 5 #define Que(rt,x,y) que(rt,1,n,x,y) 6 #define Len (dep[x]-dep[top[x]]+1) 7 using namespace std; 8 struct node 9 { 10 int f,s,F,S,sum; 11 node(long long a,long long b,long long c,long long d,long long e) 12 { 13 f=a%MOD;s=b%MOD;F=c%MOD;S=d%MOD;sum=e%MOD; 14 } 15 node() 16 { 17 } 18 } tr[40000001]; 19 int ls[40000001],rs[40000001]; 20 int TIME,E,NODE,n,m,p,q,x,y;char ch;bool rev; 21 int pos[200001],start[200001],en[200001]; 22 int dep[200001],top[200001],fa[200001],root[200001]; 23 int to[400001],nex[400001],fir[200001],size[200001]; 24 long long f[200001]; 25 int son(int x,int y) 26 { 27 while(dep[fa[top[y]]]>dep[x]) y=fa[top[y]]; 28 if(fa[top[y]]==x) return top[y]; 29 else return pos[start[x]+1]; 30 } 31 void add(int p,int q) 32 { 33 to[++E]=q;nex[E]=fir[p];fir[p]=E; 34 } 35 int build(int now,int fat) 36 { 37 fa[now]=fat; 38 dep[now]=dep[fat]+1; 39 size[now]=1; 40 for(int i=fir[now];i;i=nex[i]) 41 if(to[i]!=fat) 42 size[now]+=build(to[i],now); 43 return size[now]; 44 } 45 void pou(int now,int Top) 46 { 47 top[now]=Top;start[now]=++TIME;pos[TIME]=now; 48 int id=0; 49 for(int i=fir[now];i;i=nex[i]) 50 if(to[i]!=fa[now]) 51 if(!id || size[to[i]]>size[id]) id=to[i]; 52 if(id) pou(id,Top); 53 for(int i=fir[now];i;i=nex[i]) 54 if(to[i]!=fa[now] && to[i]!=id) 55 pou(to[i],to[i]); 56 en[now]=TIME; 57 } 58 int lca(int x,int y) 59 { 60 for(;top[x]!=top[y];x=fa[top[x]]) 61 if(fa[top[x]]<fa[top[y]]) swap(x,y); 62 return dep[x]>dep[y]?y:x; 63 } 64 long long fib(int F,int S,int x) 65 { 66 if(x==1) return F; 67 if(x==2) return S; 68 return (f[x-2]*F+f[x-1]*S)%MOD; 69 } 70 long long getsum(int now,int x,int y) 71 { 72 if(y==1) return (tr[now].f+tr[now].F)%MOD; 73 if(x==1 && y==2) return ((tr[now].f+tr[now].F)%MOD+(tr[now].s+tr[now].S)%MOD)%MOD; 74 if(x==2 && y==2) return (tr[now].s+tr[now].S)%MOD; 75 int F=(((y&1?1:-1)*f[y-2]*tr[now].F-(y&1?1:-1)*f[y-1]*tr[now].S)%MOD+MOD)%MOD,S=(((y&1?-1:1)*f[y-3]*tr[now].F+(y&1?1:-1)*f[y-2]*tr[now].S)%MOD+MOD)%MOD; 76 return (fib(tr[now].f,tr[now].s,y+2)-fib(tr[now].f,tr[now].s,x+1)+MOD+fib(F,S,y-x+3)-S+MOD)%MOD; 77 } 78 int que(int now,int l,int r,int x,int y) 79 { 80 if(!now) return 0; 81 if(l==x && r==y) 82 return tr[now].sum; 83 int ret=getsum(now,x-l+1,y-l+1); 84 if(x<=mid) ret=(ret+que(ls[now],l,mid,x,min(y,mid)))%MOD; 85 if(y>mid) ret=(ret+que(rs[now],mid+1,r,max(mid+1,x),y))%MOD; 86 return ret; 87 } 88 int add(int acc,int l,int r,int x,int y,int st,bool rev) 89 { 90 int now=++NODE; 91 if(NODE>40000000) while(1); 92 tr[now]=tr[acc]; 93 if(l==x && r==y) 94 { 95 if(rev) tr[now]=node(tr[acc].f,tr[acc].s,tr[acc].F+f[st],tr[acc].S+f[st-1],tr[acc].sum+f[st+2]-f[st+l-r+1]+MOD); 96 else tr[now]=node(tr[acc].f+f[st],tr[acc].s+f[st+1],tr[acc].F,tr[acc].S,tr[acc].sum+f[st+r-l+2]-f[st+1]+MOD); 97 ls[now]=ls[acc];rs[now]=rs[acc]; 98 return now; 99 } 100 if(x<=mid && y<=mid) 101 ls[now]=add(ls[acc],l,mid,x,y,st,rev),rs[now]=rs[acc]; 102 else 103 if(y>mid && x>mid) 104 ls[now]=ls[acc],rs[now]=add(rs[acc],mid+1,r,x,y,st,rev); 105 else 106 { 107 ls[now]=add(ls[acc],l,mid,x,mid,st,rev); 108 rs[now]=add(rs[acc],mid+1,r,mid+1,y,st+(rev?-1:1)*(mid-x+1),rev); 109 } 110 tr[now].sum=(tr[ls[now]].sum+tr[rs[now]].sum+getsum(now,1,r-l+1))%MOD; 111 return now; 112 } 113 int main() 114 { 115 scanf("%d%d",&n,&m); 116 for(int i=1;i<n;i++) 117 scanf("%d%d",&p,&q), 118 add(p,q),add(q,p); 119 build(1,0);pou(1,1); 120 f[1]=1;f[2]=1; 121 for(int i=3;i<=n+10;i++) 122 { 123 f[i]=f[i-2]+f[i-1]; 124 if(f[i]>MOD) f[i]-=MOD; 125 } 126 root[0]=1;NODE=1; 127 int lastans=0; 128 for(int i=1;i<=m;i++) 129 { 130 root[i]=root[i-1]; 131 char S[10]; 132 scanf("%s",&S); 133 if(S[0]==‘A‘) 134 { 135 scanf("%d%d",&x,&y); 136 if(!DEBUG) 137 x^=lastans; 138 if(x>n) while(1); 139 bool rev=0;int len=1,leng=dep[x]+dep[y]-2*dep[lca(x,y)]+1; 140 for(;top[x]!=top[y];x=fa[top[x]]) 141 { 142 if(dep[top[x]]<dep[top[y]]) swap(x,y),rev^=1; 143 if(rev) leng-=Len;else len+=Len; 144 root[i]=add(root[i],1,n,start[top[x]],start[x],rev?leng+1:len-1,!rev); 145 } 146 if(dep[x]>dep[y]) swap(x,y),rev^=1; 147 root[i]=add(root[i],1,n,start[x],start[y],rev?leng:len,rev); 148 } 149 if(S[0]==‘R‘) 150 { 151 scanf("%d",&x); 152 if(!DEBUG) 153 x^=lastans; 154 if(x>=i) while(1); 155 root[i]=root[x]; 156 } 157 if(S[0]==‘Q‘) 158 { 159 scanf("%d%d",&x,&y); 160 if(!DEBUG) 161 x^=lastans; 162 if(x>n) while(1); 163 int t=lca(x,y); 164 if(S[1]==‘S‘) 165 if(x!=y) 166 if(t==y) 167 { 168 int tem=son(y,x); 169 lastans=(Que(root[i],1,n)-Que(root[i],start[tem],en[tem])+MOD)%MOD; 170 } 171 else 172 lastans=Que(root[i],start[y],en[y]); 173 else 174 lastans=Que(root[i],1,n); 175 else 176 { 177 lastans=0; 178 for(;top[x]!=top[y];x=fa[top[x]]) 179 { 180 if(dep[top[x]]<dep[top[y]]) swap(x,y); 181 lastans+=Que(root[i],start[top[x]],start[x]); 182 lastans%=MOD; 183 } 184 if(dep[x]>dep[y]) swap(x,y); 185 lastans+=Que(root[i],start[x],start[y]); 186 lastans%=MOD; 187 } 188 printf("%d\n",lastans); 189 } 190 } 191 return 0; 192 }
以上是关于codechef FIBTREE 码农题 线段树 树剖 标记永久化的主要内容,如果未能解决你的问题,请参考以下文章
LUOGU P1505 [国家集训队]旅游 (树链剖分+线段树)
[CodeChef - STREETTA] The Street 李超线段树