1. 程式人生 > >luoguP2590 [ZJOI2008]樹的統計 [樹鏈剖分] [TLE的LCT]

luoguP2590 [ZJOI2008]樹的統計 [樹鏈剖分] [TLE的LCT]

efi swap ase update tle down 不用 輸入 roo

題目描述

一棵樹上有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 }

luoguP2590 [ZJOI2008]樹的統計 [樹鏈剖分] [TLE的LCT]