bzoj3551
3551: [ONTAK2010]Peaks加强版
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 877 Solved: 297
[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
Source
题解:
过了这么久才又开始写博客(省选被虐成渣,现在还要准备半期考试 only shit)好吧,算了毕竟太渣,不多说了,写题解QAQ
看了题目,一脸懵逼,怎么写?(不会) 怎么办?(看题解)
首先看看这道题,它是一个无向图,根本不知道怎么来写主席树,操蛋。
仔细看看题,我们可以这样想,我要走一个边权比x小的边,并且一直走下去,我们不就可以用最小生成树吗?每次走最小的边,那么一定是最优的,所以我们就用kruskal来写
但是要注意的是,在找到一个新的边时,新建一个节点,权值为边的权值,把边的两端连向这个点,不难证明这是一课树。。。。。
然后每次询问就从当前点往上面倍增地跳,直到不能走(点权大于x) 那么那个点的子树中的点就是我可以到达的点
于是题目就变成求一个子树第k大的问题。。。用lca加和主席树就A了
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 #define maxn 300005 7 #define maxnode 2000005 8 using namespace std; 9 int n,m,q,lastans,top; 10 int size,tot,ext; 11 int pre[maxn],now[maxn],v[maxn],fa[maxn],sum[maxnode],son[maxnode][2],pp[maxn]; 12 int bin[20],deep[maxn],f[maxn][20],mx[maxn][20]; 13 int h[maxn],list[maxn],qz[maxn],root[maxn],st[maxn],ed[maxn]; 14 bool vis[maxn]; 15 struct date{int u,v,val; 16 }a[500005]; 17 int read() 18 { 19 int x=0; char ch; bool bo=0; 20 while (ch=getchar(),ch<'0'||ch>'9') if (bo=='-') bo=1; 21 while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9'); 22 if (bo) return -x; return x; 23 } 24 bool cmp_val(date a, date b) 25 { 26 return a.val<b.val; 27 } 28 int find(int x) 29 { 30 if (fa[x]!=x) fa[x]=find(fa[x]); 31 return fa[x]; 32 } 33 void insert(int x,int y){tot++; pre[tot]=now[x]; now[x]=tot; v[tot]=y; 34 } 35 void ins(int l,int r,int x,int &y,int val) 36 { 37 int t; 38 if (!y) y=++tot; sum[y]=sum[x]+1; 39 if (l==r) return; 40 int mid=(l+r)>>1; 41 if (val<=mid) t=0,r=mid; else t=1,l=mid+1; 42 son[y][t^1]=son[x][t^1]; 43 ins(l,r,son[x][t],son[y][t],val); 44 } 45 void dfs(int x) 46 { 47 vis[x]=1; pp[++top]=x; 48 for (int i=1; i<=16; i++) 49 if (bin[i]<=deep[x]) 50 { 51 f[x][i]=f[f[x][i-1]][i-1]; 52 mx[x][i]=max(mx[x][i-1],mx[f[x][i-1]][i-1]); 53 } 54 for (int p=now[x]; p; p=pre[p]) 55 { 56 int son=v[p]; 57 deep[son]=deep[x]+1; 58 f[son][0]=x; 59 mx[son][0]=qz[x]; 60 dfs(son); 61 } 62 if (x>n) pp[++top]=x; 63 } 64 void build() 65 { 66 ext=n; 67 sort(a+1,a+m+1,cmp_val); 68 for (int i=1; i<=m; i++) 69 { 70 int q=find(a[i].u),p=find(a[i].v); 71 if (q!=p) 72 { 73 ext++; 74 fa[q]=fa[p]=ext; qz[ext]=a[i].val; 75 insert(ext,p); insert(ext,q); 76 if (ext==2*n-1) break; 77 } 78 } 79 for (int i=1; i<=n; i++) 80 { 81 if (!vis[i]) dfs(find(i)); 82 } 83 for (int i=1; i<=top; i++) 84 { 85 int t=pp[i]; 86 if (t<=n) ins(1,n,root[i-1],root[i],h[t]); 87 else 88 { 89 root[i]=root[i-1]; 90 if (!st[t]) st[t]=i; else ed[t]=i; 91 } 92 } 93 } 94 int valfind(int x,int val) 95 { 96 for(int i=17;i>=0;i--) 97 if(deep[x]>=bin[i]&&mx[x][i]<=val)x=f[x][i]; 98 return x; 99 } 100 int query(int l,int r,int x,int y,int val) 101 { 102 if (l==r) return l; 103 int mid=(l+r)>>1; 104 int kk=sum[son[y][0]]-sum[son[x][0]],t; 105 //cout<<" "<<kk<<endl; 106 if (kk>=val) return query(l,mid,son[x][0],son[y][0],val); 107 else return query(mid+1,r,son[x][1],son[y][1],val-kk); 108 } 109 void solve() 110 { 111 while (q--) 112 { 113 int x=read(),val=read(),k=read(); 114 if (lastans!=-1) x^=lastans,val^=lastans,k^=lastans; 115 int t=valfind(x,val); 116 int a=root[st[t]],b=root[ed[t]]; 117 if (sum[b]-sum[a]<k) lastans=-1; 118 else lastans=list[query(1,n,a,b,sum[b]-sum[a]-k+1)]; 119 printf("%d\n",lastans); 120 } 121 122 } 123 void prework() 124 { 125 bin[0]=1; 126 for (int i=1; i<20; i++) bin[i]=bin[i-1]<<1; 127 for (int i=1; i<=2*n; i++) fa[i]=i; 128 sort(list+1,list+1+n); 129 for (int i=1; i<=n; i++) h[i]=lower_bound(list+1,list+1+n,h[i])-list; 130 for (int i=1; i<=m; i++) 131 { 132 a[i].u=read(); a[i].v=read(); a[i].val=read(); 133 } 134 build(); 135 } 136 int main() 137 { 138 n=read(); m=read(); q=read(); 139 for (int i=1; i<=n; i++) list[i]=h[i]=read(); 140 prework(); 141 solve(); 142 return 0; 143 }
我太蒟蒻了,所以神犇们留下意见让我跪膜