标签:waiting following 勿喷 tput ace after tran ... data
Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 11250 | Accepted: 3111 |
Description
Input
Output
Sample Input
3 3 1 1 2 1 2 3 2 0 2 1 2 3 0 3
Sample Output
1 3
这个题首先很容易想到是LCA,题中的每次修改可以惊天暴力地每次修改后更新一次w[]数组,复杂度本蒟蒻不会计算,猜测极限数据60s左右能跑出来吧......
那么显然这个做法是不合理的,此时需要知道一个叫做dfs序(或者叫欧拉序)的事情。
dfs序是一棵树在进行dfs遍历是组成的结点序列,是序列,不是数列。
dfs序有两种记法,本题用到的记法是每个结点进出都加进序列,显然发现每个结点都恰出现了两次,显然此时可以发现题中每次的修改仅影响到了dfs序中以某同一结点为两端的一个闭区间,这句话好绕口啊。
当然此题是个树剖水题,spli奆奆说的。
贴代码,线段树注意变通一下
代码丑陋勿喷!
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,q,s,cnt,tot; 7 struct data{ 8 int next,to,dis; 9 }edge[400010]; 10 int head[200010],getin[200010],getout[200010],f[200010][25],deep[200010],w[200010],tree[800100]; 11 void add(int start,int end,int ds){ 12 edge[++cnt].next=head[start]; 13 edge[cnt].to=end; 14 edge[cnt].dis=ds; 15 head[start]=cnt; 16 } 17 void dfs(int u){ 18 getin[u]=++tot; 19 for(int i=head[u];i;i=edge[i].next) 20 if(!deep[edge[i].to]){ 21 deep[edge[i].to]=deep[u]+1; 22 w[edge[i].to]=w[u]+edge[i].dis; 23 f[edge[i].to][0]=u; 24 dfs(edge[i].to); 25 } 26 getout[u]=++tot; 27 } 28 void work(){ 29 for(int j=0;(1<<j)<=n;j++) 30 for(int i=1;i<=n;i++) 31 if(f[i][j-1]!=-1) f[i][j]=f[f[i][j-1]][j-1]; 32 } 33 int lca(int uu,int vv){ 34 if(deep[uu]<deep[vv]) swap(uu,vv); 35 int i=0; 36 for(i=0;(1<<i)<=n;i++); 37 i--; 38 for(int j=i;j>=0;j--) 39 if(deep[uu]-(1<<j)>=deep[vv]) uu=f[uu][j]; 40 if(uu==vv) return uu; 41 for(int j=i;j>=0;j--) 42 if(f[uu][j]!=-1&&f[uu][j]!=f[vv][j]){ 43 uu=f[uu][j]; 44 vv=f[vv][j]; 45 } 46 return f[uu][0]; 47 } 48 void build(int pos,int ll,int rr){ 49 tree[pos]=0; 50 if(ll==rr) return; 51 int mid=(ll+rr)>>1; 52 build(pos<<1,ll,mid); 53 build(pos<<1|1,mid+1,rr); 54 return; 55 } 56 void down(int pos){ 57 if(tree[pos]){ 58 tree[pos<<1]+=tree[pos]; 59 tree[pos<<1|1]+=tree[pos]; 60 tree[pos]=0; 61 } 62 return; 63 } 64 int sum(int xx,int yy,int pos,int ll,int rr){ 65 if(xx==ll&&yy==rr) return tree[pos]; 66 down(pos); 67 int mid=(ll+rr)>>1; 68 if(yy<=mid) return sum(xx,yy,pos<<1,ll,mid); 69 else if(xx>mid) return sum(xx,yy,pos<<1|1,mid+1,rr); 70 else return sum(xx,mid,pos<<1,ll,mid)+sum(mid+1,yy,pos<<1|1,mid+1,rr); 71 } 72 void updata(int xx,int yy,int pos,int ll,int rr,int dd){ 73 if(xx==ll&&yy==rr){ 74 tree[pos]+=dd; 75 return; 76 } 77 down(pos); 78 int mid=(ll+rr)>>1; 79 if(yy<=mid) updata(xx,yy,pos<<1,ll,mid,dd); 80 else if(xx>mid) updata(xx,yy,pos<<1|1,mid+1,rr,dd); 81 else{ 82 updata(xx,mid,pos<<1,ll,mid,dd); 83 updata(mid+1,yy,pos<<1|1,mid+1,rr,dd); 84 } 85 return; 86 } 87 int main(){ 88 scanf("%d%d%d",&n,&q,&s); 89 int u,v,d; 90 for(int i=1;i<n;i++){ 91 scanf("%d%d%d",&u,&v,&d); 92 add(u,v,d); 93 add(v,u,d); 94 } 95 memset(f,-1,sizeof(f)); 96 deep[1]=1; 97 dfs(1); 98 work(); 99 int od,nm,vl,e; 100 build(1,1,2*n); 101 for(int i=1;i<=q;i++){ 102 scanf("%d",&od); 103 if(od){ 104 scanf("%d%d",&nm,&vl); 105 int tmp,tu,tv; 106 tu=edge[nm<<1].to; 107 tv=edge[(nm<<1)-1].to; 108 if(f[tu][0]==tv) tmp=tu; 109 else tmp=tv; 110 updata(getin[tmp],getout[tmp],1,1,2*n,vl-edge[nm<<1].dis); 111 edge[nm<<1].dis=vl; 112 edge[(nm<<1)-1].dis=vl; 113 } 114 if(!od){ 115 scanf("%d",&e); 116 int d1=w[s]+sum(getin[s],getin[s],1,1,n<<1); 117 int d2=w[e]+sum(getin[e],getin[e],1,1,n<<1); 118 int d3=w[lca(s,e)]+sum(getin[lca(s,e)],getin[lca(s,e)],1,1,n<<1); 119 printf("%d\n",d1+d2-2*d3); 120 s=e; 121 } 122 } 123 return 0; 124 }
LCA+线段树/树状数组 POJ2763 Housewife Wind
标签:waiting following 勿喷 tput ace after tran ... data
原文地址:http://www.cnblogs.com/sdfzxh/p/6986610.html