bzoj2325 [ZJOI2011]道馆之战

来源:互联网 发布:汉客和爱华仕 知乎 编辑:程序博客网 时间:2024/05/17 07:47

【题意】n个结点的树,每个结点表示一个1*2房间。m个操作,每个操作单点修改或链查询最长路。

【数据范围】n<=30000,m<=80000

【思路】树链剖分。对于每个线段树上的结点,mx[0/1][0/1]表示从区间左上/左下走到区间右上/右下的最长路(无解则mx=0),lx[0/1]表示从区间左上/左下出发向右走的最长距离,rx[0/1]表示从区间右上/右下出发向左走的最长距离。以上信息可以合并,故直接维护即可。

【时间复杂度】O(n log n+m log^2 n)

#include<cstdio>#include<cstring>#include<algorithm>#define N 30010using namespace std;struct edge{int x, y, next;}a[N*2];struct tt{int a, b, l, r, mx[2][2], lx[2], rx[2];}t[N*2];struct dd{int l, r;}d1[N], d2[N];struct data{int s[2][2];}T;int n, m, p[N], l, x, y, map[N][2], def[N], size[N], led[N], pos[N], fa[N], c[N],l1, l2, ans, xx, yy, now0, now1, ff, x0, x1;char S[10], S1[10];void add(int x, int y){a[++l].x=x; a[l].y=y; a[l].next=p[x]; p[x]=l;}void dfs(int x){size[x]=1;for(int i=p[x]; i; i=a[i].next)if(fa[x]!=a[i].y){fa[a[i].y]=x; def[a[i].y]=def[x]+1;dfs(a[i].y); size[x]+=size[a[i].y];}}void dfs1(int x){pos[x]=++l; c[l]=x;int mx=0, v=0;for(int i=p[x]; i; i=a[i].next)if(fa[x]!=a[i].y&&mx<size[a[i].y]){mx=size[a[i].y]; v=a[i].y;}if(v){led[v]=led[x]; dfs1(v);}for(int i=p[x]; i; i=a[i].next)if(fa[x]!=a[i].y&&v!=a[i].y){led[a[i].y]=a[i].y; dfs1(a[i].y);}}void update(int i){int l=t[i].l, r=t[i].r;for(int j=0; j<=1; j++)for(int k=0; k<=1; k++){t[i].mx[j][k]=0;if(t[l].mx[j][0]&&t[r].mx[0][k])t[i].mx[j][k]=max(t[i].mx[j][k], t[l].mx[j][0]+t[r].mx[0][k]);if(t[l].mx[j][1]&&t[r].mx[1][k])t[i].mx[j][k]=max(t[i].mx[j][k], t[l].mx[j][1]+t[r].mx[1][k]);}for(int j=0; j<=1; j++){t[i].lx[j]=t[l].lx[j];if(t[l].mx[j][0])t[i].lx[j]=max(t[i].lx[j], t[l].mx[j][0]+t[r].lx[0]);if(t[l].mx[j][1])t[i].lx[j]=max(t[i].lx[j], t[l].mx[j][1]+t[r].lx[1]);}for(int j=0; j<=1; j++){t[i].rx[j]=t[r].rx[j];if(t[r].mx[0][j])t[i].rx[j]=max(t[i].rx[j], t[r].mx[0][j]+t[l].rx[0]);if(t[r].mx[1][j])t[i].rx[j]=max(t[i].rx[j], t[r].mx[1][j]+t[l].rx[1]);}}void maketree(int L, int R){t[l].a=L; t[l].b=R; t[l].l=t[l].r=0;t[l].mx[0][0]=t[l].mx[0][1]=t[l].mx[1][0]=t[l].mx[1][1]=0;t[l].lx[0]=t[l].lx[1]=t[l].rx[0]=t[l].rx[1]=0;if(L<R){int mid=(L+R)>>1, l1=l;l++; t[l1].l=l; maketree(L, mid);l++; t[l1].r=l; maketree(mid+1, R);update(l1);}else{if(map[c[L]][0]&&!map[c[L]][1]){t[l].mx[0][0]=t[l].lx[0]=t[l].rx[0]=1;}if(!map[c[L]][0]&&map[c[L]][1]){t[l].mx[1][1]=t[l].lx[1]=t[l].rx[1]=1;}if(map[c[L]][0]&&map[c[L]][1]){t[l].mx[0][0]=t[l].mx[1][1]=1;t[l].mx[0][1]=t[l].mx[1][0]=2;t[l].lx[0]=t[l].lx[1]=t[l].rx[0]=t[l].rx[1]=2;}}}void ins(int i, int x){if(t[i].a==t[i].b){t[i].mx[0][0]=t[i].mx[0][1]=t[i].mx[1][0]=t[i].mx[1][1]=0;t[i].lx[0]=t[i].lx[1]=t[i].rx[0]=t[i].rx[1]=0;if(map[c[x]][0]&&!map[c[x]][1]){t[i].mx[0][0]=t[i].lx[0]=t[i].rx[0]=1;}if(!map[c[x]][0]&&map[c[x]][1]){t[i].mx[1][1]=t[i].lx[1]=t[i].rx[1]=1;}if(map[c[x]][0]&&map[c[x]][1]){t[i].mx[0][0]=t[i].mx[1][1]=1;t[i].mx[0][1]=t[i].mx[1][0]=2;t[i].lx[0]=t[i].lx[1]=t[i].rx[0]=t[i].rx[1]=2;}return;}int mid=(t[i].a+t[i].b)>>1;if(x<=mid)ins(t[i].l, x); else ins(t[i].r, x);update(i);}data cmx(int i, int a, int b){if(a<=t[i].a&&t[i].b<=b){data T;for(int j=0; j<=1; j++)for(int k=0; k<=1; k++)T.s[j][k]=t[i].mx[j][k];return T;}int mid=(t[i].a+t[i].b)>>1;if(b<=mid)return cmx(t[i].l, a, b);if(a>mid)return cmx(t[i].r, a, b);data t1=cmx(t[i].l, a, b), t2=cmx(t[i].r, a, b), T;for(int j=0; j<=1; j++)for(int k=0; k<=1; k++){T.s[j][k]=0;if(t1.s[j][0]&&t2.s[0][k])T.s[j][k]=max(T.s[j][k], t1.s[j][0]+t2.s[0][k]);if(t1.s[j][1]&&t2.s[1][k])T.s[j][k]=max(T.s[j][k], t1.s[j][1]+t2.s[1][k]);}return T;}int clx(int i, int a, int b, int p){if(a<=t[i].a&&t[i].b<=b)return t[i].lx[p];int mid=(t[i].a+t[i].b)>>1;if(b<=mid)return clx(t[i].l, a, b, p);if(a>mid)return clx(t[i].r, a, b, p);int mx=clx(t[i].l, a, b, p); data T=cmx(t[i].l, a, b);if(T.s[p][0])mx=max(mx, T.s[p][0]+clx(t[i].r, a, b, 0));if(T.s[p][1])mx=max(mx, T.s[p][1]+clx(t[i].r, a, b, 1));return mx;}int crx(int i, int a, int b, int p){if(a<=t[i].a&&t[i].b<=b)return t[i].rx[p];int mid=(t[i].a+t[i].b)>>1;if(b<=mid)return crx(t[i].l, a, b, p);if(a>mid)return crx(t[i].r, a, b, p);int mx=crx(t[i].r, a, b, p); data T=cmx(t[i].r, a, b);if(T.s[0][p])mx=max(mx, T.s[0][p]+crx(t[i].l, a, b, 0));if(T.s[1][p])mx=max(mx, T.s[1][p]+crx(t[i].l, a, b, 1));return mx;}int main(){scanf("%d%d", &n, &m);l=0; memset(p, 0, sizeof(p));for(int i=1; i<=n-1; i++){scanf("%d%d", &x, &y);add(x, y); add(y, x);}for(int i=1; i<=n; i++){scanf("%s", S);map[i][0]=S[0]=='.'?1:0;map[i][1]=S[1]=='.'?1:0;}fa[1]=0; def[1]=1; dfs(1);l=0; led[1]=1; dfs1(1);l=1; maketree(1, n);for(int i=1; i<=m; i++){scanf("%s", S1);if(S1[0]=='Q'){scanf("%d%d", &x, &y); l1=l2=0;while(led[x]!=led[y]){xx=led[x]; yy=led[y];if(def[xx]>=def[yy]){d1[++l1].l=pos[xx]; d1[l1].r=pos[x];x=fa[xx];}if(def[yy]>=def[xx]){d2[++l2].l=pos[yy]; d2[l2].r=pos[y];y=fa[yy];}}if(def[x]>=def[y]){d1[++l1].l=pos[y]; d1[l1].r=pos[x];}else{d2[++l2].l=pos[x]; d2[l2].r=pos[y];}ans=now0=now1=0; ff=1;for(int j=1; j<=l1&&ff; j++){if(now0>-1)ans=max(ans, now0+crx(1, d1[j].l, d1[j].r, 0));if(now1>-1)ans=max(ans, now1+crx(1, d1[j].l, d1[j].r, 1));T=cmx(1, d1[j].l, d1[j].r);x0=x1=-1;if(now0>-1){if(T.s[0][0])x0=max(x0, now0+T.s[0][0]);if(T.s[1][0])x1=max(x1, now0+T.s[1][0]);}if(now1>-1){if(T.s[0][1])x0=max(x0, now1+T.s[0][1]);if(T.s[1][1])x1=max(x1, now1+T.s[1][1]);}now0=x0; now1=x1;if(now0==-1&&now1==-1)ff=0;}for(int j=l2; j&&ff; j--){if(now0>-1)ans=max(ans, now0+clx(1, d2[j].l, d2[j].r, 0));if(now1>-1)ans=max(ans, now1+clx(1, d2[j].l, d2[j].r, 1));T=cmx(1, d2[j].l, d2[j].r);x0=x1=-1;if(now0>-1){if(T.s[0][0])x0=max(x0, now0+T.s[0][0]);if(T.s[0][1])x1=max(x1, now0+T.s[0][1]);}if(now1>-1){if(T.s[1][0])x0=max(x0, now1+T.s[1][0]);if(T.s[1][1])x1=max(x1, now1+T.s[1][1]);}now0=x0; now1=x1;if(now0==-1&&now1==-1)ff=0;}printf("%d\n", ans);}else{scanf("%d%s", &x, S);map[x][0]=S[0]=='.'?1:0;map[x][1]=S[1]=='.'?1:0;ins(1, pos[x]);}}return 0;}

0 0
原创粉丝点击