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 码农题 线段树 树剖 标记永久化的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2157 旅行(树链剖分码农题)

LUOGU P1505 [国家集训队]旅游 (树链剖分+线段树)

[SHOI2008]堵塞的交通

[CodeChef - STREETTA] The Street 李超线段树

Codechef SEP14 QRECT cdq分治+线段树

[Codechef - ADITREE] Adi and the Tree - 树链剖分,线段树