zoukankan      html  css  js  c++  java
  • Bzoj3730 震波

    Time Limit: 15 Sec  Memory Limit: 256 MB
    Submit: 753  Solved: 176

    Description

    在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
    不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
    接下来你需要在线处理M次操作:
    0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
    1 x y 表示第x个城市的价值变成了y。
    为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。

    Input

    第一行包含两个正整数N和M。
    第二行包含N个正整数,第i个数表示value[i]。
    接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
    接下来M行,每行包含三个数,表示M次操作。

    Output

    包含若干行,对于每个询问输出一行一个正整数表示答案。

    Sample Input

    8 1
    1 10 100 1000 10000 100000 1000000 10000000
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    3 8
    0 3 1

    Sample Output

    11100101

    HINT

    1<=N,M<=100000

    1<=u,v,x<=N

    1<=value[i],y<=10000

    0<=k<=N-1

    Source

    传说中的动态点分治

    记录下每个点x的parent结点(即管辖x的分治结点),每次修改时暴力修改这些点。由于分治的性质,最多需要修改logN个结点。

    建好分治树后,用树状数组以距离为下标维护:和点x的距离为[下标]的点的权值和。为了去重,需要开两个树状数组,一个维护当前点到当前分治中心的答案,一个维护当前点到上一次分治中心,利用容斥原理计算。

    写了大半天,累。敲完代码先花了好久来查错,之后是无尽的TLE。

    大概是常数太大了,优化失败,只能放弃。之后看了别人的模板,重写了一遍,又开始长久的调试……

    ↑这里遇到一个超大的坑:dev c++重构代码之后选了重新编译,它竟然没有替换掉旧的exe文件!(可能是版本问题),我对照着旧代码的exe文件改新代码,怪不得怎么改都没效果……浪费了半个钟头才察觉到这一问题,比较绝望。

    排除问题之后,总算是A掉了,跑了9s

    ----第二天早晨,翻出了刚开始那版代码,觉得还有小地方可以优化,又试了试——居然14.6秒卡过去了……就很气

    RE+TLE加起来刷了9条……一半是因为dev的bug

    14.6s的超慢代码

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int mxn=200010;
     10 int read(){
     11     int x=0,f=1;char ch=getchar();
     12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     14     return x*f;
     15 }
     16 struct edge{
     17     int v,nxt;
     18 }e[mxn<<1];
     19 int hd[mxn],mct=0;
     20 void add_edge(int u,int v){
     21     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
     22 }
     23 int n,m;
     24 int w[mxn];
     25 //
     26 int fa[mxn][20];
     27 int L_dep[mxn];
     28 void LCA_DFS(int u,int ff){
     29     L_dep[u]=L_dep[ff]+1;
     30     for(int i=hd[u];i;i=e[i].nxt){
     31         if(e[i].v==ff)continue;
     32         fa[e[i].v][0]=u;
     33         LCA_DFS(e[i].v,u);
     34     }
     35     return;
     36 }
     37 void LCA_init(){
     38     for(int i=1;i<=18;i++)
     39         for(int j=1;j<=n;j++)
     40             fa[j][i]=fa[fa[j][i-1]][i-1];
     41     return;
     42 }
     43 int LCA(int x,int y){
     44     if(L_dep[x]<L_dep[y])swap(x,y);
     45     for(int i=18;i>=0;i--)
     46         if(L_dep[fa[x][i]]>=L_dep[y])x=fa[x][i];
     47     if(x==y)return y;
     48     for(int i=18;i>=0;i--)
     49         if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}
     50     return fa[x][0];
     51 }
     52 int dist(int x,int y){
     53     int tmp=LCA(x,y);
     54     return L_dep[x]-L_dep[tmp]*2+L_dep[y];
     55 }
     56 //
     57 vector<int>t[mxn][2];
     58 void update(int x,int y,int pos,int v){//结点 模式 位置 增加值 
     59 //  printf("update:%d  %d  pos:%d  v:%d
    ",x,y,pos,v);
     60     int ed=t[x][y].size()-1;++pos;
     61     for(int i=pos;i<=ed;i+=i&-i)t[x][y][i]+=v;
     62     return;
     63 }
     64 int query(int x,int y,int pos){
     65     int size=t[x][y].size();
     66     int st=min(pos+1,size-1);
     67     int res=0;
     68     for(int i=st;i;i-=i&-i)res+=t[x][y][i];
     69     return res;
     70 }
     71 //
     72 int dep[mxn],sz[mxn],mc[mxn],rt;
     73 int pr[mxn];
     74 int smm;
     75 bool vis[mxn];
     76 void DFS_sz(int u,int fa){
     77     sz[u]=1;mc[u]=0;
     78     for(int i=hd[u];i;i=e[i].nxt){
     79         int v=e[i].v;
     80         if(v==fa || vis[v])continue;
     81         DFS_sz(v,u);
     82         sz[u]+=sz[v];
     83         mc[u]=max(mc[u],sz[v]);
     84     }
     85     mc[u]=max(mc[u],smm-mc[u]);
     86     if(mc[u]<mc[rt])rt=u;
     87     return;
     88 }
     89 void add(int u,int rot,int fa){
     90 //  printf("add: u:%d rot:%d fa:%d
    ",u,rot,fa);
     91 //  printf("dist:%d
    ",dist(u,rot));
     92     update(rot,0,dist(u,rot),w[u]);
     93     if(pr[rot])update(rot,1,dist(u,pr[rot]),w[u]);
     94     for(int i=hd[u];i;i=e[i].nxt){
     95         int v=e[i].v;
     96         if(vis[v] || v==fa)continue;
     97         add(v,rot,u);
     98     }
     99     return;
    100 }
    101 void solve(int x,int fa){
    102 //  printf("solving:%d %d
    ",x,fa);
    103     vis[x]=1;pr[x]=fa;
    104     t[x][0].resize(smm+5);
    105     t[x][1].resize(smm+5);
    106     add(x,x,0);
    107     for(int i=hd[x];i;i=e[i].nxt){
    108         int v=e[i].v;
    109         if(vis[v])continue;
    110         smm=sz[v];
    111         rt=0;
    112         DFS_sz(v,x);
    113         solve(rt,x);
    114     }
    115     return;
    116 }
    117 void Upd(int x,int v){
    118     for(int y=x;y;y=pr[y]){
    119         update(y,0,dist(x,y),v-w[x]);
    120         if(pr[y])update(y,1,dist(x,pr[y]),v-w[x]);
    121     }
    122     return;
    123 }
    124 int Que(int x,int k){
    125 //  printf("QUE:%d %d
    ",x,k);
    126     int res=0;res+=query(x,0,k);
    127 //  printf("res:%d
    ",res);
    128     for(int y=x;pr[y];y=pr[y]){
    129         int dd=dist(x,pr[y]);
    130         if(k<dd)continue;
    131         res+=query(pr[y],0,k-dd);
    132 //      printf("r1:%d
    ",res);
    133         res-=query(y,1,k-dd);
    134 //      printf("r2:%d
    ",res);
    135     }
    136 //  int di=dist(x,pr[x]);
    137 //  if(pr[x] && di<k)res-=query(x,1,k-di);
    138 //  if(pr[x] && di<k)res+=Que(pr[x],k-di);
    139     return res;
    140 }
    141 //
    142 int main(){
    143     int i,j,u,v;
    144     int last=0;
    145     n=read();m=read();
    146     for(i=1;i<=n;i++)w[i]=read();
    147     for(i=1;i<n;i++){
    148         u=read();v=read();
    149         add_edge(u,v);
    150         add_edge(v,u);
    151     }
    152     mc[rt=0]=1e8;
    153     smm=n;
    154     LCA_DFS(1,0);
    155     LCA_init();
    156     DFS_sz(1,0);
    157     solve(rt,0);
    158     //
    159     int x,y,k,op;
    160     while(m--){
    161         op=read();x=read();x^=last;
    162         if(op){//update
    163             y=read()^last;
    164             Upd(x,y);
    165             w[x]=y;
    166         }
    167         else{//query
    168             k=read()^last;
    169             last=Que(x,k);
    170             printf("%d
    ",last);
    171         }
    172     }
    173     return 0;
    174 }
    View Code

    8.9s的略快代码

    那个getship()是从别处学来的,感觉思路清奇

      1 /*by SilverN*/
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int mxn=120010;
     10 int read(){
     11     int x=0,f=1;char ch=getchar();
     12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     14     return x*f;
     15 }
     16 struct edge{
     17     int v,nxt;
     18 }e[mxn<<1];
     19 int hd[mxn],mct=0;
     20 void add_edge(int u,int v){
     21     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
     22 }
     23 int n,m;
     24 int w[mxn];
     25 //
     26 int sz[mxn],mc[mxn],rt,smm;
     27 int fa[mxn][20],dis[mxn][20],dep[mxn];
     28 vector<int>t[mxn][2];
     29 bool vis[mxn];
     30 void DFS_sz(int u,int fa){
     31     sz[u]=1;mc[u]=0;
     32     for(int i=hd[u];i;i=e[i].nxt){
     33         int v=e[i].v;if(v==fa || vis[v])continue;
     34         DFS_sz(v,u);
     35         sz[u]+=sz[v];
     36         mc[u]=max(mc[u],sz[v]);
     37     }
     38     mc[u]=max(mc[u],smm-sz[u]);
     39     if(mc[u]<mc[rt])rt=u;
     40     return;
     41 }
     42 void getship(int u,int an,int ff,int d){
     43     for(int i=hd[u];i;i=e[i].nxt){
     44         int v=e[i].v;if(vis[v] || v==ff)continue;
     45         fa[v][++dep[v]]=an;
     46         dis[v][dep[v]]=d;
     47         getship(v,an,u,d+1);
     48     }
     49     return;
     50 }
     51 void solve(int x){
     52     vis[x]=1;
     53     getship(x,x,0,1);
     54     t[x][0].resize(smm+3);t[x][1].resize(smm+3);
     55     int tmp=smm;
     56     for(int i=hd[x];i;i=e[i].nxt){
     57         int v=e[i].v;
     58         if(vis[v])continue;
     59         smm=sz[v];if(smm>sz[x])smm=tmp-sz[x];
     60         rt=0;
     61         DFS_sz(v,x);
     62         solve(rt);
     63     }
     64     return;
     65 }
     66 //
     67 void add(int x,int y,int pos,int v){
     68     int ed=t[x][y].size()-1;
     69     for(int i=pos;i && i<=ed;i+=i&-i)t[x][y][i]+=v;
     70     return;
     71 }
     72 int qsum(int x,int y,int k){
     73     int res=0;
     74     if(!y)res+=w[x];
     75     int size=t[x][y].size()-1;
     76     k=min(k,size);
     77     for(int i=k;i;i-=i&-i)res+=t[x][y][i];
     78     return res;
     79 }
     80 void Upd(int x,int v){
     81     add(x,1,dis[x][dep[x]],v);
     82     for(int i=dep[x];i;i--){
     83         add(fa[x][i],0,dis[x][i],v);
     84         add(fa[x][i],1,dis[x][i-1],v);
     85     }
     86     return;
     87 }
     88 int Que(int x,int k){
     89     int res=qsum(x,0,k);
     90     for(int i=dep[x];i;i--)
     91         if(dis[x][i]<=k){
     92             res+=qsum(fa[x][i],0,k-dis[x][i])-qsum(fa[x][i+1],1,k-dis[x][i]);
     93         }
     94     return res;
     95 }
     96 //
     97 int main(){
     98     int i,j,u,v;
     99     n=read();m=read();
    100     for(i=1;i<=n;i++)w[i]=read();
    101     for(i=1;i<n;i++){
    102         u=read();v=read();
    103         add_edge(u,v);
    104         add_edge(v,u);
    105     }
    106     mc[0]=1e8;rt=0;
    107     smm=n;
    108     DFS_sz(1,0);
    109     solve(rt);
    110     for(i=1;i<=n;i++)fa[i][dep[i]+1]=i;
    111     for(i=1;i<=n;i++)Upd(i,w[i]);
    112     int x,y,k,op,last=0;
    113 //    printf("fin
    ");//bug
    114     while(m--){
    115         op=read();x=read();x^=last;
    116         if(op){//update
    117             y=read()^last;
    118             Upd(x,y-w[x]);
    119             w[x]=y;
    120         }
    121         else{//query
    122             k=read()^last;
    123             last=Que(x,k);
    124             printf("%d
    ",last);
    125         }
    126     }
    127     return 0;
    128 }
  • 相关阅读:
    React-使用combineReducers完成对数据对拆分管理
    Linux
    Linux
    linux
    linux
    Linux
    Linux
    Linux
    Linux
    Linux 系统基础优化和常用命令
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6422348.html
Copyright © 2011-2022 走看看