luoguP2590 [ZJOI2008]树的统计 [树链剖分] [TLE的LCT]

题目描述

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

我们将以下面的形式来要求你对这棵树完成一些操作:

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

注意:从点u到点v的路径上的节点包括u和v本身

输入输出格式

输入格式:

输入文件的第一行为一个整数n,表示节点的个数。

接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

接下来一行n个整数,第i个整数wi表示节点i的权值。

接下来1行,为一个整数q,表示操作的总数。

接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

输出格式:

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

输入输出样例

输入样例#1:
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
输出样例#1:
4
1
2
2
10
6
5
6
5
16

说明

对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。


 

这题本身应该是一题树链剖分果题。。QAQ

  1 //不用lazy-tag真是爽! 
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<iostream>
  5 using namespace std;
  6 #define inf 0x3f3f3f3f
  7 #define ls x<<1
  8 #define rs x<<1|1
  9 
 10 int read(){
 11     char ch;
 12     int re=0;
 13     bool flag=0;
 14     while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
 15     ch=='-'?flag=1:re=ch-'0';
 16     while((ch=getchar())>='0'&&ch<='9')  re=re*10+ch-'0';
 17     return flag?-re:re;
 18 }
 19 
 20 struct Edge{
 21     int to,nxt;
 22     Edge(int to=0,int nxt=0):
 23         to(to),nxt(nxt){}
 24 };
 25 
 26 struct Segment{
 27     int l,r,su,mx;
 28     Segment(){
 29         mx=-inf;
 30     }
 31 };
 32 
 33 const int maxn=30005;
 34 
 35 int n,m,cnt=0,dc=1;
 36 int head[maxn],val[maxn];
 37 int top[maxn],dep[maxn],fa[maxn],id[maxn],son[maxn],sz[maxn];
 38 Edge G[maxn<<1];
 39 Segment T[maxn<<2];
 40 
 41 inline void a_ed(int from,int to){
 42     G[++cnt]=Edge(to,head[from]),head[from]=cnt;
 43     G[++cnt]=Edge(from,head[to]),head[to]=cnt;
 44 }
 45 
 46 inline void push_up(int x){
 47     T[x].mx=max(T[ls].mx,T[rs].mx);
 48     T[x].su=T[ls].su+T[rs].su;
 49 }
 50 
 51 void build(int x,int l,int r){
 52     T[x].l=l,T[x].r=r;
 53     if(l==r){
 54         T[x].su=T[x].mx=val[l];
 55         return;
 56     }
 57     int mid=l+r>>1;
 58     build(ls,l,mid);  build(rs,mid+1,r);
 59     push_up(x);
 60 }
 61 
 62 void update(int x,int M,int c){
 63     if(T[x].l==T[x].r){
 64         T[x].su=T[x].mx=c;
 65         return;
 66     }
 67     int mid=T[x].l+T[x].r>>1;
 68     if(M<=mid)  update(ls,M,c);
 69     else  update(rs,M,c);
 70     push_up(x);
 71 }
 72 
 73 int query(int x,int L,int R,bool kind){
 74     if(L<=T[x].l&&T[x].r<=R)
 75         if(kind)  return T[x].su;
 76         else  return T[x].mx;
 77     int mid=T[x].l+T[x].r>>1;
 78     if(R<=mid)  return query(ls,L,R,kind);
 79     else  if(L>mid)  return query(rs,L,R,kind);
 80     else{
 81         if(kind)  return query(ls,L,mid,kind)+query(rs,mid+1,R,kind);
 82         else  return max(query(ls,L,mid,kind),query(rs,mid+1,R,kind));
 83     }
 84 }
 85 
 86 void dfs1(int no,int p){
 87     fa[no]=p;
 88     sz[no]=1;
 89     dep[no]=dep[p]+1;
 90     for(int e=head[no];e;e=G[e].nxt){
 91         int nt=G[e].to;
 92         if(nt!=p){
 93             dfs1(nt,no);
 94             sz[no]+=sz[nt];
 95             if(!son[no]||sz[nt]>sz[son[no]])
 96                 son[no]=nt;
 97         }
 98     }
 99 }
100 
101 void dfs2(int no,int p){
102     if(!son[no])  return;
103     top[son[no]]=top[no];
104     id[son[no]]=++dc;
105     dfs2(son[no],no);
106     for(int e=head[no];e;e=G[e].nxt){
107         int nt=G[e].to;
108         if(nt!=p&&nt!=son[no]){
109             top[nt]=nt;
110             id[nt]=++dc;
111             dfs2(nt,no);
112         }
113     }
114 }
115 
116 int calc(int x,int y,bool kind){
117     int sum=0,f1=top[x],f2=top[y];
118     if(!kind)  sum=-inf;
119     while(f1!=f2){
120         if(dep[f1]<dep[f2]){  swap(f1,f2),swap(x,y);  }
121         if(kind)
122             sum+=query(1,id[f1],id[x],kind);
123         else
124             sum=max(sum,query(1,id[f1],id[x],kind));
125         x=fa[f1];
126         f1=top[x];
127     }
128     if(dep[x]>dep[y])  swap(x,y);
129     if(kind)  sum+=query(1,id[x],id[y],kind);
130     else  sum=max(sum,query(1,id[x],id[y],kind));
131     return sum;
132 }
133 
134 int main(){
135 //    freopen("temp.in","r",stdin);
136     n=read();    
137     for(int i=1,from,to;i<n;i++){
138         from=read();  to=read();
139         a_ed(from,to);
140     }
141     dfs1(1,0);
142     top[1]=1;
143     id[1]=1;
144     dfs2(1,0);
145     for(int i=1;i<=n;i++)  val[id[i]]=read();
146     build(1,1,n);
147     m=read();
148     char opt[10];
149     int x,y;
150     while(m--){
151         scanf("%s",opt);
152         x=read(),y=read();
153         switch(opt[1]){
154             case 'H':{
155                 update(1,id[x],y);
156                 break;
157             }
158             case 'M':{
159                 printf("%d\n",calc(x,y,0));
160                 break;
161             }
162             default:{
163                 printf("%d\n",calc(x,y,1));
164                 break;
165             }
166         }
167     }
168     return 0;
169 }

刚学了LCT的我。。想用LCT过了这一题。。

可是。。T了。。QAQ

顺便终于明白、、把一堆变量包进一个结构体里还不用指针构成的splay还不如拆成一个个数组。。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 using namespace std;
  5 #define rint register int
  6 #define inf 0x3f3f3f3f
  7 
  8 int read(){
  9     char ch;
 10     int re=0;
 11     bool flag=0;
 12     while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
 13     ch=='-'?flag=1:re=ch-'0';
 14     while((ch=getchar())>='0'&&ch<='9')  re=re*10+ch-'0';
 15     return flag?-re:re;
 16 }
 17 
 18 struct Edge{
 19     int to,nxt;
 20     Edge(int to=0,int nxt=0):
 21         to(to),nxt(nxt){}
 22 };
 23 
 24 const int maxn=30005;
 25 
 26 int n,m,cnt=0,top;
 27 //struct 变 数组 
 28 int ch[maxn][2],su[maxn],mx[maxn],fa[maxn],rev[maxn];
 29 int head[maxn],val[maxn],stk[maxn];
 30 Edge G[maxn<<1];
 31 
 32 inline void a_ed(int from,int to){
 33     G[++cnt]=Edge(to,head[from]);
 34     head[from]=cnt;
 35     G[++cnt]=Edge(from,head[to]);
 36     head[to]=cnt;
 37 }
 38 
 39 inline void push_up(int x){
 40     mx[x]=max(mx[ch[x][0]],max(mx[ch[x][1]],val[x]));
 41     su[x]=su[ch[x][0]]+su[ch[x][1]]+val[x];
 42 }
 43 
 44 inline void push_down(int x){
 45     if(rev[x]){
 46         rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
 47         swap(ch[x][0],ch[x][1]);
 48         rev[x]=0;
 49     }
 50 }
 51 
 52 inline bool isroot(int x){
 53     return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
 54 }
 55 
 56 void rot(int x){
 57     int y=fa[x],z=fa[y],l,r;
 58     fa[x]=z;
 59     if(!isroot(y))  ch[z][ch[z][1]==y]=x;
 60     if(ch[y][0]==x)  l=0;
 61     else  l=1;
 62     r=l^1;
 63     fa[ch[x][r]]=y;
 64     ch[y][l]=ch[x][r];
 65     fa[y]=x;
 66     ch[x][r]=y;
 67     push_up(y),push_up(x);
 68 }
 69 
 70 void splay(int x){
 71     top=1;  stk[top]=x;
 72     for(rint i=x;!isroot(i);i=fa[i])  stk[++top]=fa[i];
 73     for(rint i=top;i;i--)  push_down(stk[i]);
 74     while(!isroot(x)){
 75         int y=fa[x],z=fa[y];
 76         if(!isroot(y)){
 77             if((ch[y][0]==x)^(ch[z][0]==y))  rot(x);
 78             else  rot(y);
 79         }
 80         rot(x);
 81     }
 82 }
 83 
 84 void acc(int x){
 85     int t=0;
 86     while(x){
 87         splay(x);
 88         ch[x][1]=t;
 89         push_up(x);
 90         t=x;  x=fa[x];
 91     }
 92 }
 93 
 94 void make_root(int x){  acc(x),splay(x),rev[x]^=1;  }
 95 
 96 void split(int x,int y){  make_root(x),acc(y),splay(y);  }
 97 
 98 void dfs(int no,int fat){
 99     fa[no]=fat;
100     for(rint e=head[no];e;e=G[e].nxt)
101         if(G[e].to!=fat)
102             dfs(G[e].to,no);
103 }
104 
105 int main(){
106 //    freopen("temp.in","r",stdin);
107     n=read();
108     for(rint i=1,from,to;i<n;i++){
109         from=read(),to=read();
110         a_ed(from,to);
111     }
112     memset(mx,-inf,(n+1)<<2);
113     for(rint i=1;i<=n;i++){
114         val[i]=read();
115         su[i]=mx[i]=val[i];
116     }
117     dfs(1,0);
118     char opt[10];  int x,y;
119     m=read();
120     while(m--){
121         scanf("%s",opt);
122         x=read(),y=read();
123         switch(opt[1]){
124             case 'H':{
125                 acc(x);
126                 splay(x);
127                 val[x]=y;
128                 push_up(x);
129                 break;
130             }
131             case 'M':{
132                 split(x,y);
133                 printf("%d\n",mx[y]);
134                 break;
135             }
136             default:{
137                 split(x,y);
138                 printf("%d\n",su[y]);
139                 break;
140             }
141         }
142     }
143     return 0;
144 }

 

posted @ 2017-08-16 22:08  ZYBGMZL  阅读(243)  评论(0编辑  收藏  举报