【BZOJ3531】【SDOI2014】旅行

题目传送门

题目大意:给定一棵无根树,每个节点有自己的类别和权值,现在给定两个类别相同的点,叫你求这2点路径上同类别节点的权值和/最大权值。

节点类别与权值会改变。

解题思路:考虑对每一个类别开一棵线段树,动态开点,可以写指针,也可以开数组写链表,然后剩下的就是树剖的东西了。我写的是指针,跑的略慢一些,时间效率为\( O(q \log^{2} n) \).

代码由于是在自家的mac上码的,所以和以前风格不大一样。

  1 #include <stdio.h>
  2 #define MN 100005
  3 inline void swp(int &a,int &b){a ^= b ^= a ^= b;}
  4 inline int max(int a,int b){return a > b ? a : b;}
  5 inline int in(){
  6     int x = 0 ,f = 1; char ch = getchar();
  7     while (ch < '0' || ch > '9') f = ch=='-' ? -1 :1 , ch = getchar();
  8     while (ch >= '0' && ch <= '9' ) x = (x<<3) + (x<<1) + ch - '0',ch = getchar();
  9     return x*f;
 10 }
 11 struct segment_tree{
 12     segment_tree *ls , *rs;
 13     int sum,ma;
 14     void combine(){
 15         sum = ma = 0;
 16         if (ls != NULL){
 17             sum += ls -> sum;
 18             ma = max( ma , ls -> ma );
 19         }if (rs != NULL){
 20             sum += rs -> sum;
 21             ma = max( ma , rs -> ma );
 22         }
 23     }
 24     segment_tree (int sum=0,int ma=0):sum(sum),ma(ma){ls = rs = NULL;}
 25 }*ST[MN];
 26 #define S_T segment_tree
 27 int to[MN<<1],nxt[MN<<1],cnt,head[MN];
 28 int n,q,top[MN],siz[MN],son[MN],val[MN],belief[MN],fa[MN],dep[MN],pos[MN],dfsn;
 29 inline void ins(int x,int y){to[++cnt] = y , nxt[cnt] = head[x] , head[x] = cnt;}
 30 inline void insw(int x,int y){ins(x,y); ins(y,x);}
 31 inline void dfs1(int u,int f,int d){
 32     siz[u] = 1; dep[u] = d; fa[u] = f;
 33     for (register int i = head[u]; i; i = nxt[i])
 34         if (to[i] != f) {
 35             dfs1(to[i],u,d+1); siz[u] += siz[to[i]];
 36             if (siz[son[u]] < siz[to[i]]) son[u] = to[i];
 37         }
 38 }
 39 inline void dfs2(int u,int tp){
 40     top[u] = tp; pos[u] = (++dfsn); if (son[u]) dfs2(son[u],tp);
 41     for (register int i = head[u]; i; i = nxt[i])
 42         if (to[i] != fa[u] && to[i] != son[u]) dfs2(to[i],to[i]);
 43 }
 44 #define mid (l+r>>1)
 45 inline void insert(S_T* &x,int l,int r,int pos,int val){
 46     if (x == NULL) x = new S_T;
 47     if (l == r){x -> sum = x -> ma = val; return;}
 48     if (pos <= mid) insert(x -> ls,l,mid,pos,val);
 49     else insert(x -> rs,mid+1,r,pos,val);x->combine();
 50 }
 51 inline void Delete(S_T* &x,int l,int r,int pos){
 52     if (l==r){delete x; x = NULL; return; }
 53     if (pos<=mid) Delete(x -> ls,l,mid,pos);
 54     else Delete(x -> rs,mid+1,r,pos);
 55     if (x -> ls == NULL && x -> rs == NULL){delete x; x = NULL; return; }
 56     else x -> combine();
 57 }
 58 inline int QM(S_T* &x,int l,int r,int a,int b){
 59     if (x == NULL) return 0;
 60     if (l == a && r == b) return x -> ma;
 61     if (b<=mid) return QM(x -> ls,l,mid,a,b);
 62     if (a>mid) return QM(x -> rs,mid+1,r,a,b);
 63     return max(QM(x -> ls,l,mid,a,mid),QM(x -> rs,mid+1,r,mid+1,b));
 64 }
 65 inline int QS(S_T* &x,int l,int r,int a,int b){
 66     if (x == NULL) return 0;
 67     if (l == a && r == b) return x -> sum;
 68     if (b<=mid) return QS(x -> ls,l,mid,a,b);
 69     if (a>mid) return QS(x -> rs,mid+1,r,a,b);
 70     return QS(x -> ls,l,mid,a,mid)+QS(x -> rs,mid+1,r,mid+1,b);
 71 }
 72 inline int qm(int belief,int x,int y){
 73     register int res = 0;
 74     while (top[x] != top[y]){
 75         if (dep[top[x]] < dep[top[y]]) swp(x,y);
 76         res = max(res,QM(ST[belief],1,n,pos[top[x]],pos[x]));
 77         x = fa[top[x]];
 78     }if (dep[x] > dep[y]) swp(x,y);res = max(res,QM(ST[belief],1,n,pos[x],pos[y]));
 79     return res;
 80 }
 81 inline int qs(int belief,int x,int y){
 82     register int res = 0;
 83     while (top[x] != top[y]){
 84         if (dep[top[x]] < dep[top[y]]) swp(x,y);
 85         res += QS(ST[belief],1,n,pos[top[x]],pos[x]);
 86         x = fa[top[x]];
 87     }if (dep[x] > dep[y]) swp(x,y);res += QS(ST[belief],1,n,pos[x],pos[y]);
 88     return res;
 89 }
 90 void init(){
 91     n = in() , q = in();
 92     for (int i = 1; i <= n; ++i) val[i] = in() , belief[i] = in();
 93     for (register int i = 1; i < n; ++i) insw(in(),in());
 94     dfs1(1,1,1);dfs2(1,1);
 95     for (register int i = 1; i <= n; ++i)
 96         insert(ST[belief[i]],1,n,pos[i],val[i]);
 97 }
 98 void solve(){
 99     while(q--){
100         register char op[5]; scanf("%s",op);
101         register int x=in(),y=in();
102         if (op[0] == 'C'){
103             if (op[1] == 'C'){
104                 Delete(ST[belief[x]],1,n,pos[x]);
105                 insert(ST[belief[x] = y],1,n,pos[x],val[x]);
106             }else insert(ST[belief[x]],1,n,pos[x],val[x]=y);
107         }else{
108             if (op[1] == 'M') printf("%d\n",qm(belief[x],x,y));
109             else printf("%d\n",qs(belief[x],x,y));
110         }
111     }
112 }
113 int main(){ init(); solve();}

 

posted @ 2017-04-30 17:41  Melacau  阅读(360)  评论(0编辑  收藏  举报