[BZOJ4811][Ynoi2017]由乃的OJ:树链剖分,线段树/LCT+按位贪心

这道题树链剖分或是动态树都可以做(不过我的动态树BZOJ上TLE了,可见LCT常数很大),思路什么的不会看别人的博客就好,这里就不多扯了。

这里贴一个:

https://www.cnblogs.com/Narh/p/9171362.html

树链剖分代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #define ls (o<<1)
  5 #define rs ((o<<1)|1)
  6 #define mid ((l+r)>>1)
  7 using namespace std;
  8 typedef unsigned long long LL;
  9 inline LL read(){
 10     LL x=0;char ch=getchar();
 11     while(ch<'0'||ch>'9')ch=getchar();
 12     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
 13     return x;
 14 }
 15 const int SIZE=100005;
 16 const LL U=-1;
 17 int n,m,k;
 18 int typ[SIZE];LL num[SIZE];
 19 int fa[SIZE],dep[SIZE],pc[SIZE],siz[SIZE],top[SIZE],id[SIZE],tot;
 20 int op[SIZE],loc,ktyp,ql,qr;
 21 LL w[SIZE],knum;
 22 struct Node{
 23     LL l[2],r[2];
 24 };
 25 Node S,a[SIZE*4],sav[2][SIZE];
 26 int len[2];
 27 int head[SIZE],ecnt;
 28 struct Edge{
 29     int to,next;
 30 }e[SIZE*2];
 31 void add_edge(int bg,int ed){
 32     ecnt++;
 33     e[ecnt].next=head[bg];
 34     e[ecnt].to=ed;
 35     head[bg]=ecnt;
 36 }
 37 void dfs1(int x,int pre,int depth){
 38     fa[x]=pre;
 39     dep[x]=depth;
 40     siz[x]=1;
 41     int maxsiz=-1;
 42     for(int i=head[x];i;i=e[i].next){
 43         int go=e[i].to;
 44         if(go==pre) continue;
 45         dfs1(go,x,depth+1);
 46         siz[x]+=siz[go];
 47         if(siz[go]>maxsiz){
 48             maxsiz=siz[go];
 49             pc[x]=go;
 50         }
 51     }
 52 }
 53 void dfs2(int x,int topf){
 54     top[x]=topf;
 55     id[x]=++tot;
 56     op[tot]=typ[x];
 57     w[tot]=num[x];
 58     if(!pc[x]) return;
 59     dfs2(pc[x],topf);
 60     for(int i=head[x];i;i=e[i].next){
 61         int go=e[i].to;
 62         if(go==fa[x]||go==pc[x]) continue;
 63         dfs2(go,go);
 64     }
 65 }
 66 Node trans(int p,LL x){
 67     Node ans;
 68     if(p==1){
 69         ans.l[0]=ans.r[0]=(x&0);
 70         ans.l[1]=ans.r[1]=(x&U);
 71     }
 72     if(p==2){
 73         ans.l[0]=ans.r[0]=(x|0);
 74         ans.l[1]=ans.r[1]=(x|U);
 75     }
 76     if(p==3){
 77         ans.l[0]=ans.r[0]=(x^0);
 78         ans.l[1]=ans.r[1]=(x^U);
 79     }
 80     return ans;
 81 }
 82 Node merge(Node x,Node y){
 83     Node ans;
 84     ans.l[0]=((x.l[0]&y.l[1])|((~x.l[0])&y.l[0]));
 85     ans.l[1]=((x.l[1]&y.l[1])|((~x.l[1])&y.l[0]));
 86     ans.r[0]=((y.r[0]&x.r[1])|((~y.r[0])&x.r[0]));
 87     ans.r[1]=((y.r[1]&x.r[1])|((~y.r[1])&x.r[0]));
 88     return ans;
 89 }
 90 Node rev(Node x){
 91     swap(x.l[0],x.r[0]);
 92     swap(x.l[1],x.r[1]);
 93     return x;
 94 }
 95 void pushup(int o){
 96     a[o]=merge(a[ls],a[rs]);
 97 }
 98 void build(int o,int l,int r){
 99     if(l==r){
100         a[o]=trans(op[l],w[l]);
101         return;
102     }
103     build(ls,l,mid);
104     build(rs,mid+1,r);
105     pushup(o);
106 }
107 void update(int o,int l,int r){
108     if(l==r&&l==loc){
109         a[o]=trans(ktyp,knum);
110         return;
111     }
112     if(loc<=mid) update(ls,l,mid);
113     else update(rs,mid+1,r);
114     pushup(o);
115 }
116 Node query(int o,int l,int r){
117     if(ql<=l&&r<=qr)
118         return a[o];
119     Node ans=S;
120     if(mid>=ql) ans=merge(ans,query(ls,l,mid));
121     if(mid<qr) ans=merge(ans,query(rs,mid+1,r));
122     return ans;
123 }
124 Node statistic(int x,int y){
125     len[0]=len[1]=0;
126     int r=1;
127     while(top[x]!=top[y]){
128         if(dep[top[x]]<dep[top[y]]){
129             swap(x,y);
130             r^=1;
131         }
132         ql=id[top[x]],qr=id[x];
133         sav[r][++len[r]]=query(1,1,n);
134         x=fa[top[x]];
135     }
136     r^=1;
137     if(dep[x]>dep[y]){
138         swap(x,y);
139         r^=1;
140     }
141     ql=id[x],qr=id[y];
142     sav[r][++len[r]]=query(1,1,n);
143     Node ans=S;
144     for(int i=1;i<=len[1];i++)
145         ans=merge(ans,rev(sav[1][i]));
146     for(int i=len[0];i;i--)
147         ans=merge(ans,sav[0][i]);
148     return ans;
149 }
150 LL greedy_algo(Node x,LL z){
151     LL ans=0;
152     for(int i=63;i+1;i--){
153         if((x.l[0]>>i)&1){
154             ans+=((LL)1<<i);
155             continue;
156         }
157         if(((LL)1<<i)<=z&&((x.l[1]>>i)&1)){
158             ans+=((LL)1<<i);
159             z-=((LL)1<<i);
160             continue;
161         }
162     }
163     return ans;
164 }
165 int main(){
166     S.l[0]=S.r[0]=0;
167     S.l[1]=S.r[1]=U;
168     n=read();m=read();k=read();
169     for(int i=1;i<=n;i++){
170         typ[i]=read();
171         num[i]=read();
172     }
173     for(int i=1;i<n;i++){
174         int u=read(),v=read();
175         add_edge(u,v);
176         add_edge(v,u);
177     }
178     dfs1(1,0,1);
179     dfs2(1,1);
180     build(1,1,n);
181     while(m--){
182         int opt=read();
183         if(opt==1){
184             int x=read(),y=read();
185             LL z=read();
186             Node rez=statistic(x,y);
187             LL ans=greedy_algo(rez,z);
188             printf("%llu\n",ans);
189         }
190         else if(opt==2){
191             loc=read(),ktyp=read();
192             knum=read();
193             loc=id[loc];
194             update(1,1,n);
195         }
196     }
197     return 0;
198 }

动态树(LCT)代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 using namespace std;
  4 typedef unsigned long long LL;
  5 inline LL read(){
  6     LL x=0,f=1;char ch=getchar();
  7     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  8     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
  9     return x*f;
 10 }
 11 const int MAXN=100005;
 12 const LL U=-1;
 13 int n,m,k,fa[MAXN],ch[MAXN][2],tag[MAXN],stack[MAXN],top;
 14 struct Node{
 15     LL l0,l1,r0,r1;
 16     friend Node operator + (Node lf,Node rt){
 17         Node ans;
 18         ans.l0=((lf.l0&rt.l1)|((~lf.l0)&rt.l0));
 19         ans.l1=((lf.l1&rt.l1)|((~lf.l1)&rt.l0));
 20         ans.r0=((rt.r0&lf.r1)|((~rt.r0)&lf.r0));
 21         ans.r1=((rt.r1&lf.r1)|((~rt.r1)&lf.r0));
 22         return ans;
 23     }
 24 }a[MAXN],b[MAXN];
 25 #define lc ch[x][0]
 26 #define rc ch[x][1]
 27 inline bool isroot(int x){
 28     return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
 29 }
 30 inline void pushup(int x){
 31     b[x]=(b[lc]+a[x])+b[rc];
 32 }
 33 inline void pushr(int x){
 34     swap(lc,rc);
 35     swap(b[x].l0,b[x].r0);
 36     swap(b[x].l1,b[x].r1);
 37     tag[x]^=1;
 38 }
 39 inline void pushdown(int x){
 40     if(!tag[x]) return;
 41     if(lc) pushr(lc);
 42     if(rc) pushr(rc);
 43     tag[x]=0;
 44 }
 45 inline void calc(int x,int opt,LL k){
 46     if(opt==1){
 47         a[x].l0=a[x].r0=(0&k);
 48         a[x].l1=a[x].r1=(U&k);
 49     }
 50     else if(opt==2){
 51         a[x].l0=a[x].r0=(0|k);
 52         a[x].l1=a[x].r1=(U|k);
 53     }
 54     else{
 55         a[x].l0=a[x].r0=(0^k);
 56         a[x].l1=a[x].r1=(U^k);
 57     }
 58     b[x]=a[x];
 59 }
 60 inline void rotate(int x){
 61     int y=fa[x],z=fa[y],f=(ch[y][1]==x),g=ch[x][f^1];
 62     if(!isroot(y)) ch[z][ch[z][1]==y]=x;
 63     ch[x][f^1]=y;
 64     ch[y][f]=g;
 65     if(g) fa[g]=y;
 66     fa[y]=x;
 67     fa[x]=z;
 68     pushup(y);
 69     pushup(x);
 70 }
 71 inline void splay(int x){
 72     int y=x,z;
 73     stack[top=1]=y;
 74     while(!isroot(y)) stack[++top]=(y=fa[y]);
 75     while(top) pushdown(stack[top--]);
 76     while(!isroot(x)){
 77         y=fa[x],z=fa[y];
 78         if(!isroot(y)){
 79             if((ch[y][0]==x)^(ch[z][0]==y)) rotate(x);
 80             else rotate(y);
 81         }
 82         rotate(x);
 83     }
 84 }
 85 inline void access(int x){
 86     for(int y=0;x;x=fa[y=x]){
 87         splay(x);
 88         rc=y;
 89         pushup(x);
 90     }
 91 }
 92 inline void makeroot(int x){
 93     access(x);
 94     splay(x);
 95     pushr(x);
 96 }
 97 inline void split(int x,int y){
 98     makeroot(x);
 99     access(y);
100     splay(y);
101 }
102 inline LL getans(Node x,LL lim){
103     LL ans=0; 
104     for(int i=k-1;i>=0;i--){
105         if(x.l0&((LL)1<<i)) ans+=((LL)1<<i);
106         else if(lim>=((LL)1<<i)&&(x.l1&((LL)1<<i))) ans+=((LL)1<<i),lim-=((LL)1<<i);
107     }
108     return ans;
109 }
110 inline void link(int x,int y){
111     makeroot(y);
112     fa[y]=x;
113 } 
114 int main(){
115     b[0].l0=b[0].r0=0,b[0].l1=b[0].r1=U;
116     n=read(),m=read(),k=read();
117     for(int i=1;i<=n;i++){
118         int x=read();LL y=read();
119         calc(i,x,y);
120     }
121     for(int i=1;i<n;i++){
122         int u=read(),v=read();
123         link(u,v);
124     }
125     while(m--){
126         int opt=read(),x=read(),y=read();
127         LL z=read();
128         if(opt==1){
129             split(x,y);
130             printf("%llu\n",getans(b[y],z));
131         }
132         else{
133             splay(x);
134             calc(x,y,z);
135             pushup(x);
136         }
137     }
138     return 0;
139 }

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9280070.html