bzoj 3551: [ONTAK2010]Peaks加强版

3551: [ONTAK2010]Peaks加强版

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 3889  Solved: 1143
[Submit][Status][Discuss]

Description

【题目描述】同3545

Input

第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。v=v xor lastans,x=x xor lastans,k=k xor lastans。如果lastans=-1则不变。
 

Output

同3545

Sample Input

 

Sample Output

 

HINT

 

【数据范围】同3545
 
 
这题是kruskal重构树,这题一定要在线,而3545可以离线,离线的话我们可以排序以后用线段树合并维护连通性。  
构树以后,由于答案都在子树里面,而子树在dfs序里面是一个连续的区间,所以我们维护一个主席树。 
  1 #include<bits/stdc++.h>
  2 using namespace std; 
  3 int const N=200000+10;  
  4 int const M=500000+10;  
  5 #define  mid (l+r)/2 
  6 struct edge{
  7     int to,nt;   
  8 }e[N];  
  9 struct E{
 10     int x,y,z;  
 11     bool operator < (const E &rhs) const{
 12         return z<rhs.z;  
 13     }
 14 }t[M];   
 15 int a[N],b[N],n,m,q,c[N],f[N],val[N],h[N],cnt,sum[N*20],rt[N],tin[N],tout[N],T,id[N],lch[N*20],rch[N*20];    
 16 int d[N][20],anc[N][20];  
 17 void read(int &x){
 18     x=0; char c=getchar();  
 19     while (!isdigit(c)) c=getchar();  
 20     while (isdigit(c)) x=x*10+(c^48),c=getchar(); 
 21 }
 22 int find(int x){
 23     return x==f[x]? x: f[x]=find(f[x]); 
 24 }
 25 void add(int a,int b){
 26     e[++cnt].to=b; 
 27     e[cnt].nt=h[a]; 
 28     h[a]=cnt; 
 29 } 
 30 void kruscal(){
 31     int id=n;  
 32     for(int i=1;i<2*n;i++) f[i]=i;  
 33     for(int i=1;i<=m;i++){
 34         int fx=find(t[i].x); 
 35         int fy=find(t[i].y);  
 36         if(fx!=fy){  
 37             id++;  
 38             f[fx]=f[fy]=id;  
 39             val[id]=t[i].z;  
 40             add(id,fx);     
 41             add(id,fy);  
 42             d[fx][0]=d[fy][0]=t[i].z; 
 43             anc[fx][0]=anc[fy][0]=id;     
 44             if(id==2*n-1) break;   
 45         }
 46     }
 47 }
 48 void dfs(int x){
 49     tin[x]=++T; 
 50     id[T]=x;    
 51     for(int i=h[x];i;i=e[i].nt){
 52         int v=e[i].to;  
 53         dfs(v);  
 54     }
 55     tout[x]=T;  
 56 }
 57 void insert(int now,int &x,int l,int r,int p){
 58     x=++cnt;  
 59     lch[x]=lch[now];rch[x]=rch[now];sum[x]=sum[now];  
 60     if(l==r) {
 61         sum[x]++;  
 62         return;   
 63     }
 64     if(p<=mid) insert(lch[now],lch[x],l,mid,p);  
 65     else insert(rch[now],rch[x],mid+1,r,p);  
 66     sum[x]=sum[lch[x]]+sum[rch[x]];  
 67 }
 68 int query(int x,int y,int l,int r,int k){
 69     if(l==r) return b[r];  
 70     int num=sum[lch[y]]-sum[lch[x]];  
 71     if(num>=k) return query(lch[x],lch[y],l,mid,k);  
 72     else return query(rch[x],rch[y],mid+1,r,k-num);  
 73 }
 74 int main(){
 75     //scanf("%d%d%d",&n,&m,&q); 
 76     read(n);read(m); read(q);    
 77     for(int i=1;i<=n;i++)
 78         read(a[i]),b[i]=a[i];  
 79     sort(b+1,b+n+1); 
 80     int rk=unique(b+1,b+n+1)-b-1; 
 81     for(int i=1;i<=n;i++)  
 82         c[i]=lower_bound(b+1,b+rk+1,a[i])-b; 
 83     int last=0;  
 84     for(int i=1;i<=m;i++) 
 85     //    scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].z); 
 86         read(t[i].x),read(t[i].y),read(t[i].z);    
 87     sort(t+1,t+m+1);  
 88     kruscal();        
 89     cnt=0;  
 90     for(int i=2*n-1;i>=1;i--)  
 91         if(!tin[i]) { 
 92             anc[i][0]=i;  
 93             dfs(i);  
 94         }
 95         /* 
 96      for(int i=2*n-1;i>=1;i--){
 97         cout<<i<<"*** "<<val[i]<<" ** ";  
 98         for(int j=h[i];j;j=e[j].nt){
 99             cout<<e[j].to<<" ";  
100         }
101         cout<<endl;  
102     }  */ 
103     for(int j=1;j<20;j++)  
104         for(int i=1;i<2*n;i++){
105             d[i][j]=max(d[i][j-1],d[anc[i][j-1]][j-1]);  
106             anc[i][j]=anc[anc[i][j-1]][j-1];  
107         }
108     for(int i=1;i<2*n;i++){
109         if(id[i]<=n) insert(rt[i-1],rt[i],1,rk,c[id[i]]);  
110         else rt[i]=rt[i-1];   
111     }    
112     while (q--){
113         int v,x,k;  
114     //    scanf("%d%d%d",&v,&x,&k); 
115         read(v); read(x);read(k);   
116         if(last!=-1){
117             v^=last; 
118             x^=last;  
119             k^=last;  
120         }
121         int t=v;  
122         for(int i=19;i>=0;i--)  
123             if(d[t][i]<=x) t=anc[t][i];   
124         int l=tin[t];  
125         int r=tout[t];
126         int num=sum[rt[r]]-sum[rt[l-1]];    
127         if(num<k) printf("%d\n",last=-1);  
128         else {
129             k=num-k+1;      
130             //cout<<"nima"<<k<<endl;  
131             printf("%d\n",last=query(rt[l-1],rt[r],1,rk,k)); 
132         }
133         //last=0;   
134     }
135     return 0;  
136 
137 }
View Code

 

posted @ 2019-09-12 14:32  zjxxcn  阅读(295)  评论(0编辑  收藏  举报