Bzoj3551 [ONTAK2010]Peaks加强版

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1622  Solved: 528

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

 

Source

 

破题调一整晚,还不如重写一遍呢

 

图论 生成树 kruskal重构树

 

kruskal重构树是什么?没见过的(黑)科技啊

在用kruskal建生成树时,不连接原来的边,而是新建一个结点,向要连接的两点连边,边权为原边权。

这样建出的生成树,具有自叶子向根上溯,经过边权单调不减的特性。

有张直观的示意图见:http://www.cnblogs.com/GXZlegend/p/6293547.html

 

利用这个性质,可以倍增上溯找到当前点经过权值不超过x的边能到达的最远祖先,该祖先点的子树(里的有效点)就是能到达的所有点。

在这些点里面找第k大的即可。具体可以用dfs序+主席树维护。

 

各种蠢错误不提,遇到了两个坑点:

  1、询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰

  ↑discuss里说不包括点v本身,如果从点v出发哪儿也去不了,应该输出-1。但是正确性不明,看网上题解,有的代码判了这个,有的没判,对拍时候会出错,但是似乎都可以A

  2、异或以后会出现询问v超过范围的情况,算无解。

  ↑然而popoQQQ学长和黄学长的代码好像压根儿没管这个啊QAQ,出界情况蜜汁自然溢出不影响结果,然而我一样的写法就数组溢出无限RE。

  ↑数据好像卡了v出界的情况,又规避了v在n~cnt(生成树新建的结点范围)内的询问,经测试v>n判无解和v>cnt判无解都可以过。

 

  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=101010;
 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,w;
 18 }e[mxn<<2];
 19 int hd[mxn*2],mct=0;
 20 void add_edge(int u,int v,int w){
 21     e[++mct].v=v;e[mct].w=w;e[mct].nxt=hd[u];hd[u]=mct;return;
 22 }
 23 struct Edge{
 24     int x,y,w;
 25     bool operator < (Edge b)const{return w<b.w;}
 26 }eg[mxn*5];
 27 //
 28 int dfn[mxn*2],out[mxn*2],dtime=0;
 29 bool vis[mxn*2];
 30 int dis[mxn*2],dep[mxn*2],f[mxn*2][20];
 31 int mp[mxn*2];
 32 void DFS(int u,int fa){
 33     vis[u]=1;
 34     dfn[u]=++dtime;
 35     mp[dtime]=u;
 36     dep[u]=dep[fa]+1;
 37     for(int i=1;i<19;i++) f[u][i]=f[f[u][i-1]][i-1];
 38     for(int i=hd[u],v;i;i=e[i].nxt){
 39         v=e[i].v;
 40         f[v][0]=u;
 41         dis[u]=max(dis[u],e[i].w);//要到达当前点需要经过的权值最大边 
 42         DFS(v,u);
 43     }
 44     out[u]=dtime;
 45     return;
 46 }
 47 int FTP(int u,int x){ 
 48     for(int i=18;i>=0;i--){
 49         if(dis[f[u][i]]<=x)u=f[u][i];
 50     }
 51     return u;
 52 }
 53 //
 54 struct node{
 55     int l,r;
 56     int sz;
 57 }t[mxn*50];
 58 int rt[mxn*3],root,cnt=0;
 59 void update(int p,int v,int l,int r,int y,int &rt){
 60     rt=++cnt;
 61 //  printf("update:%d %d l:%d r:%d y:%d rt:%d\n",p,v,l,r,y,rt);
 62     t[rt]=t[y];
 63     t[rt].sz++;
 64     if(l==r)return;
 65     int mid=(l+r)>>1;
 66     if(p<=mid)update(p,v,l,mid,t[y].l,t[rt].l);
 67     else update(p,v,mid+1,r,t[y].r,t[rt].r);
 68     return;
 69 }
 70 int query(int k,int l,int r,int y,int rt){
 71 //  printf("rt:%d y:%d sz:%d %d\n",rt,y,t[rt].sz,t[y].sz);
 72 //  printf("l:%d r:%d\n",l,r);
 73     if(t[rt].sz-t[y].sz<k)return -1;//无解 
 74     if(l==r)return l;
 75     int mid=(l+r)>>1;
 76     if(t[t[rt].r].sz-t[t[y].r].sz>=k)return query(k,mid+1,r,t[y].r,t[rt].r);
 77     else return query(k-t[t[rt].r].sz+t[t[y].r].sz,l,mid,t[y].l,t[rt].l);
 78 }
 79 //
 80 int n,m,Q,h[mxn],n_cnt=0;
 81 int bas[mxn],id[mxn];
 82 int lastans=0;
 83 //
 84 int fa[mxn*3];
 85 int find(int x){
 86     return fa[x]==x?x:fa[x]=find(fa[x]);
 87 }
 88 void kruskal(){
 89     sort(eg+1,eg+m+1);
 90     int i,j;
 91     for(i=1;i<=n;i++)fa[i]=i;
 92     n_cnt=n;
 93     for(i=1;i<=m;i++){
 94         int x=eg[i].x,y=eg[i].y;
 95         int u=find(x),v=find(y);
 96         if(u==v)continue;
 97         n_cnt++;
 98         fa[n_cnt]=n_cnt;
 99         add_edge(n_cnt,u,eg[i].w);
100         add_edge(n_cnt,v,eg[i].w);
101         fa[u]=n_cnt;fa[v]=n_cnt;//要更新的是u,v
102         root=n_cnt;//update root 
103         if(n_cnt==2*n-1)break;
104     }
105     return;
106 }
107 //
108 void solve(){
109     for(int i=1;i<=n_cnt;i++){
110         if(mp[i]<=n){
111             update(id[mp[i]],1,1,n,rt[i-1],rt[i]);
112         }
113         else rt[i]=rt[i-1];
114     }
115     //
116     int v,x,k;
117     for(int i=1;i<=Q;i++){
118         v=read();x=read();k=read();
119         if(lastans!=-1){//XOR
120             v^=lastans; x^=lastans; k^=lastans;
121         }
122         if(v>n_cnt || !v){
123             lastans=-1;
124             printf("-1\n");
125             continue;
126         }
127         v=FTP(v,x);
128         int pos=query(k,1,n,rt[dfn[v]],rt[out[v]]);
129         if(pos!=-1)pos=bas[pos];
130         lastans=pos;
131         printf("%d\n",pos);
132     }
133     return;
134 }
135 int main(){
136 //  freopen("Input.in","r",stdin);
137     int i,j;
138     n=read();m=read();Q=read();
139     for(i=1;i<=n;i++){
140         h[i]=read();
141         bas[i]=h[i];
142     }
143     sort(bas+1,bas+n+1);
144     int ed=unique(bas+1,bas+n+1)-bas-1;
145     for(i=1;i<=n;i++){
146         id[i]=lower_bound(bas+1,bas+ed+1,h[i])-bas;
147     }
148     for(i=1;i<=m;i++){
149         eg[i].x=read();eg[i].y=read();eg[i].w=read();
150     }
151     kruskal();
152     dis[0]=0x3f3f3f3f;//init
153     for(i=1;i<=n_cnt;i++)if(!vis[i]){
154         int x=find(i);
155         DFS(x,0);
156     }
157     solve();
158     return 0;
159 }
160 

 

posted @ 2017-04-03 11:40  SilverNebula  阅读(228)  评论(0编辑  收藏  举报
AmazingCounters.com