zoukankan      html  css  js  c++  java
  • HDU 3966 Aragorn's Story 动态树 树链剖分

    Aragorn's Story

    Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

    【Problem Description】
    Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, the enemy has N camps out of his kingdom and M edges connect them. It is guaranteed that for any two camps, there is one and only one path connect them. At first Aragorn know the number of enemies in every camp. But the enemy is cunning , they will increase or decrease the number of soldiers in camps. Every time the enemy change the number of soldiers, they will set two camps C1 and C2. Then, for C1, C2 and all camps on the path from C1 to C2, they will increase or decrease K soldiers to these camps. Now Aragorn wants to know the number of soldiers in some particular camps real-time.
     
    【Input】
    Multiple test cases, process to the end of input.
    For each case, The first line contains three integers N, M, P which means there will be N(1 ≤ N ≤ 50000) camps, M(M = N-1) edges and P(1 ≤ P ≤ 100000) operations. The number of camps starts from 1.
    The next line contains N integers A1, A2, ...AN(0 ≤ Ai ≤ 1000), means at first in camp-i has Ai enemies.
    The next M lines contains two integers u and v for each, denotes that there is an edge connects camp-u and camp-v.
    The next P lines will start with a capital letter 'I', 'D' or 'Q' for each line.
    'I', followed by three integers C1, C2 and K( 0≤K≤1000), which means for camp C1, C2 and all camps on the path from C1 to C2, increase K soldiers to these camps.
    'D', followed by three integers C1, C2 and K( 0≤K≤1000), which means for camp C1, C2 and all camps on the path from C1 to C2, decrease K soldiers to these camps.
    'Q', followed by one integer C, which is a query and means Aragorn wants to know the number of enemies in camp C at that time.
     
    【Output】
    For each query, you need to output the actually number of enemies in the specified camp.
     
    【Sample Input】
    3 2 5
    1 2 3
    2 1
    2 3
    I 1 3 5
    Q 2
    D 1 2 2
    Q 1 
    Q 3
    【Sample Output】
    7
    4
    8

    【Hint】

    1.The number of enemies may be negative.

    2.Huge input, be careful.
     
     
    【分析】
    解1:
    动态维护树中路径上点的边权值。
     
    两个点之间的路径只要找到最近公共祖先即可
    主要还是找LCA这块,动态树中的这个操作是改造一下access,然后注意各标志的下放。
     
    【教训】
    跟上一次一样,也是TLE了很久,关键在于上组数据的状态量没有清理干净,重点是father和sons没有清空,结果就被坑了很久。
    下次尤其注意!!
     
      1 /* ***********************************************
      2 MYID    : Chen Fan
      3 LANG    : G++
      4 PROG    : HDU 3966
      5 ************************************************ */
      6 
      7 #include <iostream>
      8 #include <cstdio>
      9 #include <cstring>
     10 #include <algorithm>
     11 #include <queue>
     12 
     13 using namespace std;
     14 
     15 #define MAXN (int)5E4+10
     16 #define MAXM (int)1E5+10
     17 
     18 typedef struct nod
     19 {
     20     int a,b;
     21 } node;
     22 node edge[MAXM];
     23 
     24 bool op(node a,node b)
     25 {
     26     if (a.a==b.a) return a.b<b.b;
     27     else return a.a<b.a;
     28 }
     29 
     30 int sons[MAXN][2];
     31 int father[MAXN],size[MAXN],data[MAXN],change[MAXN];
     32 int start[MAXN],num[MAXN];
     33 bool root[MAXN];
     34 
     35 void bfs(int s)
     36 {
     37     queue<int>q;
     38     q.push(s);
     39     root[s]=true;
     40     change[s]=0;
     41     while(!q.empty())
     42     {
     43         int now=q.front();
     44         for (int i=0;i<num[now];i++)
     45         if (!root[edge[start[now]+i].b])
     46         {
     47             father[edge[start[now]+i].b]=now;
     48             root[edge[start[now]+i].b]=true;
     49             change[edge[start[now]+i].b]=0;
     50             q.push(edge[start[now]+i].b);
     51         }
     52         q.pop();
     53     }
     54 }
     55 
     56 void down(int x)
     57 {
     58     if (change[x])
     59     {
     60         data[x]+=change[x];
     61         change[sons[x][0]]+=change[x];
     62         change[sons[x][1]]+=change[x];
     63         change[x]=0;
     64     }
     65 }
     66 
     67 void rotate(int x,int w) //rotate(node,0/1)
     68 {
     69     int y=father[x];
     70     
     71     down(y);
     72     down(x);
     73 
     74     sons[y][!w]=sons[x][w];
     75     if (sons[x][w]) father[sons[x][w]]=y;
     76     father[x]=father[y];
     77     if (father[y]&&(!root[y])) sons[father[y]][y==sons[father[y]][1]]=x;
     78     sons[x][w]=y;
     79     father[y]=x;
     80 
     81     if (root[y])
     82     {
     83         root[x]=true;
     84         root[y]=false;
     85     }
     86 }
     87 
     88 void splay__(int x) //splay(node)
     89 {
     90     down(x);
     91     while(!root[x])
     92     {
     93         if (root[father[x]]) rotate(x,x==sons[father[x]][0]);
     94         else 
     95         {
     96             int t=father[x];
     97             int w=(sons[father[t]][0]==t);
     98             if (sons[t][w]==x)
     99             {
    100                 rotate(x,!w);
    101                 rotate(x,w);
    102             } else 
    103             {
    104                 rotate(t,w);
    105                 rotate(x,w);
    106             }
    107         }
    108     }
    109 }
    110 
    111 void splay(int x) //splay(node)
    112 {
    113     down(x);
    114     while(!root[x])
    115     {
    116         if (sons[father[x]][0]==x) rotate(x,1);
    117         else rotate(x,0);
    118     }
    119 }
    120 
    121 void access(int v)
    122 {
    123     int u=v;
    124     v=0;
    125     while(u)
    126     {
    127         splay(u);
    128         down(u);
    129         root[sons[u][1]]=true;
    130         sons[u][1]=v;
    131         root[v]=false;
    132         v=u;
    133         u=father[u];
    134     }
    135 }
    136 
    137 void update(int v,int u,int k)
    138 {
    139     access(v);
    140     v=0;
    141     while(u)
    142     {
    143         splay(u);
    144         if (!father[u])
    145         {
    146             data[u]+=k;
    147             change[v]+=k;
    148             change[sons[u][1]]+=k;
    149             return;
    150         }
    151         down(u);
    152         root[sons[u][1]]=true;
    153         sons[u][1]=v;
    154         root[v]=false;
    155         v=u;
    156         u=father[u];
    157     }
    158 }
    159 
    160 int INT() {
    161     char ch;
    162     int res;
    163     bool neg;
    164     while (ch = getchar(), !isdigit(ch) && ch != '-')
    165         ;
    166     if (ch == '-') {
    167         neg = true;
    168         res = 0;
    169     } else {
    170         neg = false;
    171         res = ch - '0';
    172     }
    173     while (ch = getchar(), isdigit(ch))
    174         res = res * 10 + ch - '0';
    175     return neg ? -res : res;
    176 }
    177 
    178 char CHAR() {
    179     char res;
    180     while (res = getchar(), !isalpha(res))
    181         ;
    182     return res;
    183 }
    184 
    185 int main()
    186 {
    187     freopen("3966.txt","r",stdin);
    188 
    189     int n,m,p;
    190     while(scanf("%d%d%d",&n,&m,&p)!=EOF)
    191     {
    192         memset(father,0,sizeof(father));
    193         memset(sons,0,sizeof(sons));
    194 
    195         for (int i=1;i<=n;i++) data[i]=INT();
    196 
    197         for (int i=1;i<=m;i++)
    198         {
    199             int a,b;
    200             a=INT();
    201             b=INT();
    202             edge[i*2].a=a;
    203             edge[i*2].b=b;
    204             edge[i*2-1].a=b;
    205             edge[i*2-1].b=a;
    206         }
    207         m*=2;
    208         sort(&edge[1],&edge[m+1],op);
    209         memset(num,0,sizeof(num));
    210         int o=-1;
    211         for (int i=1;i<=m;i++)
    212         {
    213             if (o!=edge[i].a)
    214             {
    215                 o=edge[i].a;
    216                 start[o]=i;
    217             }
    218             num[o]++;
    219         }
    220         memset(root,0,sizeof(root));
    221         bfs(1);
    222 
    223         for (int i=1;i<=p;i++)
    224         {
    225             char s;
    226             s=CHAR();
    227             switch(s)
    228             {
    229                 case 'I':
    230                     int c1,c2,k;
    231                     c1=INT();c2=INT();k=INT();
    232                     update(c1,c2,k);
    233                     break;
    234                 case 'D':
    235                     c1=INT();c2=INT();k=INT();
    236                     update(c1,c2,-k);
    237                     break;
    238                 case 'Q':
    239                     int c;
    240                     c=INT();
    241                     splay(c);
    242                     printf("%d
    ",data[c]);
    243             }
    244         }
    245     }
    246 
    247     return 0;
    248 }
    View Code
     
    解2:
    由于这里的树结构是固定不变的,因此也可以使用树链剖分来做。
     
    【教训】
    ......DFS剖分爆栈的问题还是比较严重啊......T_T......也是第一次写,没经验,差错查了好久,用BFS代替之
      1 /* ***********************************************
      2 MYID    : Chen Fan
      3 LANG    : G++
      4 PROG    : HDU 3966_TreeCut
      5 ************************************************ */
      6 
      7 #include <iostream>
      8 #include <cstdio>
      9 #include <cstring>
     10 #include <algorithm>
     11 
     12 using namespace std;
     13 
     14 #define MAXN (int)5E4+10
     15 #define MAXM (int)1E5+10
     16 
     17 int n;
     18 
     19 int son[MAXN];
     20 int father[MAXN],size[MAXN],level[MAXN],data[MAXN],top[MAXN];
     21 int start[MAXN],num[MAXN];
     22 
     23 typedef struct nod
     24 {
     25     int a,b;
     26 } node;
     27 node edge[MAXM];
     28 
     29 bool op(node a,node b)
     30 {
     31     if (a.a==b.a) return a.b<b.b;
     32     else return a.a<b.a;
     33 }
     34 
     35 int lowbit(int s)
     36 {
     37     return s&(-s);
     38 }
     39 int c[MAXN],pos[MAXN];
     40 int tot;
     41 
     42 void update(int x,int s) 
     43 {
     44     while (x<=n)
     45     {
     46         c[x]+=s;
     47         x+=lowbit(x);
     48     }
     49 }
     50 
     51 int sum(int x)
     52 {
     53     int t=0;
     54     while (x>0)
     55     {
     56         t+=c[x];
     57         x-=lowbit(x);
     58     }
     59     return t;
     60 }
     61 
     62 void dfs(int now,int front,int d)
     63 {
     64     level[now]=d;
     65     father[now]=front;
     66     size[now]=1;
     67     for (int i=0;i<num[now];i++)
     68     {
     69         int temp=edge[start[now]+i].b;
     70         if (temp!=front)
     71         {
     72             dfs(temp,now,d+1);
     73             size[now]+=size[temp];
     74             if (son[now]==0||size[temp]>size[son[now]]) son[now]=temp;
     75         }
     76     }
     77 }
     78 
     79 int q[MAXN];
     80 void bfs()
     81 {
     82     int head=1,tail=1;
     83     q[1]=1;
     84     level[1]=0;
     85     father[1]=0;
     86     while(head<=tail)
     87     {
     88         int now=q[head];
     89         size[now]=1;
     90         for (int i=0;i<num[now];i++)
     91         {
     92             int temp=edge[start[now]+i].b;
     93             if (temp!=father[now])
     94             {
     95                 father[temp]=now;
     96                 level[temp]=level[now]+1;
     97                 tail++;
     98                 q[tail]=temp;
     99             }
    100         }
    101         head++;
    102     }
    103     for (int i=n;i>=1;i--)
    104     {
    105         int now=q[i];
    106         if (father[now])
    107         {
    108             size[father[now]]+=size[now];
    109             if (son[father[now]]==0||size[now]>size[son[father[now]]])
    110             son[father[now]]=now;
    111         }
    112     }
    113 
    114     for (int i=1;i<=n;i++)
    115     {
    116         int now=q[i];
    117         if (son[father[now]]==now) top[now]=top[father[now]];
    118         else 
    119         {
    120             top[now]=now;
    121             while(now)
    122             {
    123                 tot++;
    124                 pos[now]=tot;
    125                 now=son[now];
    126             }
    127         }
    128     }
    129 }
    130 
    131 void treecut(int now,int root)
    132 {
    133     top[now]=root;
    134     tot++;
    135     pos[now]=tot;
    136     
    137     if (!son[now]) return ;
    138     treecut(son[now],root);
    139 
    140     for (int i=0;i<num[now];i++)
    141     {
    142         int temp=edge[start[now]+i].b;
    143         if (temp!=father[now]&&temp!=son[now]) treecut(temp,temp);
    144     }
    145 }
    146 
    147 void change(int x,int y,int value)
    148 {
    149     while(top[x]!=top[y])
    150     {
    151         if (level[top[x]]<level[top[y]]) swap(x,y);
    152         update(pos[top[x]],value);
    153         update(pos[x]+1,-value);
    154         x=father[top[x]];
    155     }
    156     if (level[x]>level[y]) swap(x,y);
    157     
    158     update(pos[x],value);
    159     update(pos[y]+1,-value);
    160 }
    161 
    162 int main()
    163 {
    164     freopen("3966.txt","r",stdin);
    165 
    166     int m,p;
    167     while(scanf("%d%d%d",&n,&m,&p)!=EOF)
    168     {
    169         for (int i=1;i<=n;i++) scanf("%d",&data[i]);
    170 
    171         for (int i=1;i<=m;i++)
    172         {
    173             int a,b;
    174             scanf("%d%d",&a,&b);
    175             edge[i*2].a=a;
    176             edge[i*2].b=b;
    177             edge[i*2-1].a=b;
    178             edge[i*2-1].b=a;
    179         }
    180         m*=2;
    181         sort(&edge[1],&edge[m+1],op);
    182         memset(num,0,sizeof(num));
    183         int o=-1;
    184         for (int i=1;i<=m;i++)
    185         {
    186             if (o!=edge[i].a)
    187             {
    188                 o=edge[i].a;
    189                 start[o]=i;
    190             }
    191             num[o]++;
    192         }
    193 
    194         memset(son,0,sizeof(son));
    195         tot=0;
    196         //dfs(1,0,0);
    197         //treecut(1,1);
    198         bfs();
    199 
    200         memset(c,0,sizeof(c));
    201         for (int i=1;i<=n;i++)
    202         {
    203             update(pos[i],data[i]);
    204             update(pos[i]+1,-data[i]);
    205         }
    206 
    207         for (int i=1;i<=p;i++)
    208         {
    209             char s;
    210             s=getchar();
    211             while (s!='Q'&&s!='I'&&s!='D') s=getchar();
    212             if (s=='Q')
    213             {
    214                 int cc;
    215                 scanf("%d",&cc);
    216                 printf("%d
    ",sum(pos[cc]));
    217             } else 
    218             {
    219                 int c1,c2,k;
    220                 scanf("%d%d%d",&c1,&c2,&k);
    221                 if (s=='D') k=-k;
    222                 change(c1,c2,k);
    223             }
    224         }
    225     }
    226 
    227     return 0;
    228 }
    View Code
     
  • 相关阅读:
    基于注解的 Spring MVC 简单入门
    Spring MVC入门
    Java集合总结之Collection整体框架
    关于getClass().getClassLoader()
    Java生成和操作Excel文件
    Spring 实现发送电子邮件的两种方法
    java mail(发送邮件--163邮箱)
    Write operations are not allowed in read-only mode 只读模式下(FlushMode.NEVER/MANUAL)写操作不
    配置文件Struts.xml 中type属性 redirect,redirectAction,chain的区别
    关于Hibernate在反向工程时无法选择Spring DAO Type的解决方法【更新版】
  • 原文地址:https://www.cnblogs.com/jcf94/p/4461143.html
Copyright © 2011-2022 走看看