bzoj3545 [ONTAK2010]Peaks、bzoj3551 [ONTAK2010]Peaks加强版
题目描述:
题解:
重构树+线段树合并。
可以算是板子了吧。
代码(非强制在线):
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100050; const int M = 5*N; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c; } int n,m,q,to[N],h[N]; struct Pair { int x,y; }p[N]; bool cmp(Pair a,Pair b){return a.x<b.x;} struct Edge { int x,y,w; void rd(){read(x),read(y),read(w);} }d[M]; bool emp(Edge a,Edge b){return a.w<b.w;} int ff[N<<1],fa[N<<1][22],wg[N<<1],ch[N<<1][2]; int findff(int u){return u==ff[u]?u:ff[u]=findff(ff[u]);} void kru() { wg[0] = 0x3f3f3f3f; for(int i=1;i<=(n<<1);i++)ff[i] = i; int tot = n,sum = 0; for(int i=1;i<=m&&sum<n-1;i++) { int x = findff(d[i].x),y = findff(d[i].y); if(x!=y) { ff[x]=ff[y]=fa[x][0]=fa[y][0]=++tot; wg[tot]=d[i].w; sum++; ch[tot][0]=x,ch[tot][1]=y; } } } void init() { for(int k=1;(1<<k)<=(n<<1);k++) for(int i=1;i<(n<<1);i++) fa[i][k]=fa[fa[i][k-1]][k-1]; } int rt[N<<1]; struct segtree { int siz[70*N],ls[70*N],rs[70*N],tot; void insert(int l,int r,int&u,int qx) { if(!u)u=++tot;siz[u]++; if(l==r)return ; int mid = (l+r)>>1; if(qx<=mid)insert(l,mid,ls[u],qx); else insert(mid+1,r,rs[u],qx); } int merge(int x,int y) { if(!(x*y))return x+y; int z = ++tot; siz[z] = siz[x]+siz[y]; ls[z] = merge(ls[x],ls[y]); rs[z] = merge(rs[x],rs[y]); return z; } int query(int l,int r,int u,int qk) { if(l==r)return l; int tmp = siz[rs[u]],mid = (l+r)>>1; if(qk<=tmp)return query(mid+1,r,rs[u],qk); else return query(l,mid,ls[u],qk-tmp); } }tr; int main() { // freopen("tt.in","r",stdin); read(n),read(m),read(q); for(int i=1;i<=n;i++)read(p[i].x),p[i].y=i; sort(p+1,p+1+n,cmp); for(int las=0x3f3f3f3f,k=0,i=1;i<=n;i++) { if(las!=p[i].x) { las = p[i].x; to[++k] = las; } h[p[i].y] = k; } for(int i=1;i<=m;i++)d[i].rd(); sort(d+1,d+1+m,emp); kru();init(); for(int i=1;i<=n;i++)tr.insert(1,n,rt[i],h[i]); for(int i=n+1;i<(n<<1);i++)rt[i]=tr.merge(rt[ch[i][0]],rt[ch[i][1]]); for(int u,w,k,i=1;i<=q;i++) { read(u),read(w),read(k); for(int j=20;j>=0;j--)if(wg[fa[u][j]]<=w)u=fa[u][j]; if(tr.siz[rt[u]]<k)puts("-1"); else printf("%d\n",to[tr.query(1,n,rt[u],k)]); } return 0; }