zoukankan      html  css  js  c++  java
  • BZOJ 3531 SDOI2014 旅行 树链剖分+线段树动态开点

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531

    题意概述:
      给出一棵N个点的树,树上的每个结点有一个颜色和权值,支持以下四种操作:
      1.将点x的颜色改成c。
      2.将点x的权值给成w。
      3.询问x->y路径上和端点相同颜色的点的权值总和(端点颜色相同)。
      4.询问x->y路径上和端点相同颜色的点的权值最大值(端点颜色相同)。

    分析:

      首先树链剖分,每条链开C棵维护每个颜色的线段树。动态开点。

      感觉没什么好说的......考试的时候灵光一闪就来了......之前还在YYlct之类的......

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<queue>
      8 #include<set>
      9 #include<map>
     10 #include<vector>
     11 #include<cctype>
     12 using namespace std;
     13 const int maxn=100005;
     14 const int SIZE=4000005;
     15 
     16 int N,Q,C[maxn],W[maxn];
     17 map<int,int>rt[maxn];
     18 struct edge{ int to,next; }E[maxn<<1];
     19 int first[maxn],np,dep[maxn],top[maxn],fa[maxn],son[maxn],sz[maxn],len[maxn];
     20 int lc[SIZE],rc[SIZE],sum[SIZE],mx[SIZE],np2;
     21 
     22 void _scanf(int &x)
     23 {
     24     x=0;
     25     char ch=getchar();
     26     while(ch<'0'||ch>'9') ch=getchar();
     27     while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
     28 }
     29 void _scanf(char *s)
     30 {
     31     int cnt=0;
     32     char ch=getchar();
     33     while(!isalpha(ch)) ch=getchar();
     34     while(isalpha(ch)) s[cnt++]=ch,ch=getchar();
     35     s[cnt]='';
     36 }
     37 int out_cnt,out[15];
     38 void _printf(int x)
     39 {
     40     out[++out_cnt]=x%10,x/=10;
     41     while(x) out[++out_cnt]=x%10,x/=10;
     42     while(out_cnt) putchar('0'+out[out_cnt--]);
     43     putchar('
    ');
     44 }
     45 void add_edge(int u,int v){
     46     E[++np]=(edge){v,first[u]};
     47     first[u]=np;
     48 }
     49 void data_in()
     50 {
     51     _scanf(N);_scanf(Q);
     52     for(int i=1;i<=N;i++) _scanf(W[i]),_scanf(C[i]);
     53     int x,y;
     54     for(int i=1;i<N;i++){
     55         _scanf(x);_scanf(y);
     56         add_edge(x,y); add_edge(y,x);
     57     }
     58 }
     59 void DFS1(int i,int f,int d){
     60     fa[i]=f,dep[i]=d,sz[i]=1;
     61     for(int p=first[i];p;p=E[p].next){
     62         int j=E[p].to;
     63         if(j==f) continue;
     64         DFS1(j,i,d+1);
     65         sz[i]+=sz[j];
     66         if(sz[j]>sz[son[i]]) son[i]=j;
     67     }
     68 }
     69 void DFS2(int i,int f,int tp){
     70     top[i]=tp,len[tp]++;
     71     if(son[i]) DFS2(son[i],i,tp);
     72     for(int p=first[i];p;p=E[p].next){
     73         int j=E[p].to;
     74         if(j==f||j==son[i]) continue;
     75         DFS2(j,i,j);
     76     }
     77 }
     78 int newnode(){
     79     np2++,lc[np2]=rc[np2]=0,sum[np2]=mx[np2]=0;
     80     return np2;
     81 }
     82 void pushup(int now){
     83     mx[now]=max(mx[lc[now]],mx[rc[now]]);
     84     sum[now]=sum[lc[now]]+sum[rc[now]];
     85 }
     86 void update(int &now,int L,int R,int pos,int v){
     87     if(!now) now=newnode();
     88     if(L==R){ sum[now]=mx[now]=v; return; }
     89     int m=L+R>>1;
     90     if(pos<=m) update(lc[now],L,m,pos,v);
     91     else update(rc[now],m+1,R,pos,v);
     92     pushup(now);
     93 }
     94 void build(int i,int f){
     95     update(rt[top[i]][C[i]],0,len[top[i]]-1,dep[i]-dep[top[i]],W[i]);
     96     for(int p=first[i];p;p=E[p].next){
     97         if(E[p].to==f) continue;
     98         build(E[p].to,i);
     99     }
    100 }
    101 int query1(int now,int L,int R,int A,int B){
    102     if(!now) return 0;
    103     if(A<=L&&R<=B) return sum[now];
    104     int m=L+R>>1;
    105     if(B<=m) return query1(lc[now],L,m,A,B);
    106     if(A>m) return query1(rc[now],m+1,R,A,B);
    107     return query1(lc[now],L,m,A,B)+query1(rc[now],m+1,R,A,B);
    108 }
    109 int query2(int now,int L,int R,int A,int B){
    110     if(!now) return 0;
    111     if(A<=L&&R<=B) return mx[now];
    112     int m=L+R>>1;
    113     if(B<=m) return query2(lc[now],L,m,A,B);
    114     if(A>m) return query2(rc[now],m+1,R,A,B);
    115     return max(query2(lc[now],L,m,A,B),query2(rc[now],m+1,R,A,B));
    116 }
    117 int LCA(int x,int y){
    118     while(top[x]!=top[y]){
    119         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    120         x=fa[top[x]];
    121     }
    122     return dep[x]<dep[y]?x:y;
    123 }
    124 int query_s(int x,int y,int c){
    125     int re=0;
    126     while(top[x]!=top[y]){
    127         re+=query1(rt[top[x]][c],0,len[top[x]]-1,0,dep[x]-dep[top[x]]);
    128         x=fa[top[x]];
    129     }
    130     re+=query1(rt[top[x]][c],0,len[top[x]]-1,dep[y]-dep[top[x]],dep[x]-dep[top[x]]);
    131     return re;
    132 }
    133 int query_m(int x,int y,int c){
    134     int re=0;
    135     while(top[x]!=top[y]){
    136         re=max(re,query2(rt[top[x]][c],0,len[top[x]]-1,0,dep[x]-dep[top[x]]));
    137         x=fa[top[x]];
    138     }
    139     re=max(re,query2(rt[top[x]][c],0,len[top[x]]-1,dep[y]-dep[top[x]],dep[x]-dep[top[x]]));
    140     return re;
    141 }
    142 void work()
    143 {
    144     DFS1(1,0,1);
    145     DFS2(1,0,1);
    146     build(1,0);
    147     char op[5];
    148     int x,y,z,p,c,w,ans;
    149     for(int i=1;i<=Q;i++){
    150         _scanf(op);
    151         if(op[0]=='C'&&op[1]=='C'){
    152             _scanf(x);_scanf(c);
    153             update(rt[top[x]][C[x]],0,len[top[x]]-1,dep[x]-dep[top[x]],0);
    154             update(rt[top[x]][C[x]=c],0,len[top[x]]-1,dep[x]-dep[top[x]],W[x]);
    155         }
    156         else if(op[0]=='C'&&op[1]=='W'){
    157             _scanf(x);_scanf(w);
    158             update(rt[top[x]][C[x]],0,len[top[x]]-1,dep[x]-dep[top[x]],W[x]=w);
    159         }
    160         else if(op[1]=='S'){
    161             _scanf(x);_scanf(y);
    162             z=LCA(x,y);
    163             _printf(query_s(x,z,C[x])+query_s(y,z,C[x])-(C[z]==C[x]?W[z]:0));
    164         }
    165         else if(op[1]=='M'){
    166             _scanf(x);_scanf(y);
    167             z=LCA(x,y);
    168             _printf(max(query_m(x,z,C[x]),query_m(y,z,C[x])));
    169         }
    170     }
    171 }
    172 int main()
    173 {
    174     data_in();
    175     work();
    176     return 0;
    177 }
    View Code
     
  • 相关阅读:
    019-centos的yum用法
    018-DNS解析过程与配置DNS服务
    017-linux正则表达式
    016-sed
    014-配置SSH免密钥登录
    013-安装VNC服务
    012-centos6.5配置静态ip
    010-centos上安装matlab
    mysqlbinlog
    更换mysql数据库的datadir目录
  • 原文地址:https://www.cnblogs.com/KKKorange/p/8644896.html
Copyright © 2011-2022 走看看