1. 程式人生 > >[bzoj2733]永無鄉&&[bzoj3545]Peaks

[bzoj2733]永無鄉&&[bzoj3545]Peaks

its end sed friend bit i++ gpo pla 入門

並不敢說完全會了線段樹合並,只是至少知道原理寫法了。。。還是太菜了,每天被大佬吊錘qwq

我看到的幾道線段樹合並都是權值線段樹的合並。這個算法適用範圍應該只是01線段樹的。

這兩道算入門題了吧。。。

發現粘題面沒人看(自己都懶得看),以後粘鏈接加題意吧。

永無鄉

給$n$個沒有連邊的帶權點,動態加邊,詢問$u$所在連通塊權值第$k$大的點是什麽。$n \leq 1e5 , q\leq 3e5$

離線永無鄉??

給定森林,點有點權有重復!,邊有邊權。詢問$u$所在連通塊,只能走邊權小於$w$的邊,可達的權值第$k$大的點編號!是什麽。$n \leq 1e5 , m,q \leq 5e5$ 被坑的巨慘qwq

後面的離線一下,按邊權從小到大加進去就和永無鄉一樣了。

並查集維護連通性,並將兩個連通塊的權值線段樹合並。詢問就是在所在連通塊線段樹二分找。$(O(nlogn))$

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
inline int read(){
    int r=0,c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))
    r=r*10+c-0,c=getchar();
    return r;
}
int fa[N],rt[N],n,m;
int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } struct Node{ int L,R,sum; }T[N*20]; int sz; #define ls T[o].L #define rs T[o].R void pullup(int o){ T[o].sum=T[ls].sum+T[rs].sum; } void ins(int &o,int l,int r,int v){ if(!o)o=++sz; if(l==r){ T[o].sum=1;return; }
int mid=l+r>>1; if(v<=mid)ins(ls,l,mid,v); else ins(rs,mid+1,r,v); pullup(o); } int merge(int x,int y){ if(!x)return y; if(!y)return x; T[x].L=merge(T[x].L,T[y].L); T[x].R=merge(T[x].R,T[y].R); pullup(x); return x; } int query(int o,int l,int r,int rk){ if(l==r)return l; int mid=l+r>>1; if(rk<=T[ls].sum)return query(ls,l,mid,rk); else return query(rs,mid+1,r,rk-T[ls].sum); } void Link(int x,int y){ int u=find(x),v=find(y); fa[u]=v;rt[v]=merge(rt[u],rt[v]); } int a[N],id[N]; void init(){ n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=read(),id[a[i]]=fa[i]=i; while(m--){ int u=read(),v=read(); fa[find(u)]=find(v); } for(int i=1;i<=n;i++) ins(rt[find(i)],1,n,a[i]); } void solve(){ m=read(); char s[10]; while(m--){ scanf("%s",s); if(s[0]==B){ int u=read(),v=read(); Link(u,v); } else{ int u=find(read()),rk=read(); if(T[rt[u]].sum<rk)puts("-1"); else printf("%d\n",id[query(rt[u],1,n,rk)]); } } } int main(){ init(); solve(); }
2733

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
const int M=500010;
inline int read(){
    int r=0,c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))
    r=r*10+c-0,c=getchar();
    return r;
}
int n,m,q;
struct Edge{
    int u,v,w;
    friend bool operator < (Edge p,Edge q){
        return p.w<q.w;
    }
}e[M];
struct ask{
    int u,w,k,ans,id;
}a[M];
bool cmpw(ask p,ask q){
    return p.w<q.w;
}
bool cmpid(ask p,ask q){
    return p.id<q.id;
}
int fa[N],h[N],t[N],id[N];
inline int find(int x){
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
int rt[N],sz;
struct Node{
    int L,R,sum;
}T[N*40];
#define ls T[o].L
#define rs T[o].R
#define mid (l+r>>1)
inline void pullup(int o){
    T[o].sum=T[ls].sum+T[rs].sum;
}
void ins(int &o,int l,int r,int val){
    if(!o)o=++sz;
    if(l==r){
        T[o].sum=1;return;
    }
    if(val<=mid)ins(ls,l,mid,val);
    else ins(rs,mid+1,r,val);
    pullup(o);
}
int query(int o,int l,int r,int rk){
    if(l==r){
        return t[l];
    }
    if(rk<=T[ls].sum)return query(ls,l,mid,rk);
    else return query(rs,mid+1,r,rk-T[ls].sum);
}
int merge(int x,int y){
    if(!x)return y;
    if(!y)return x;
    if(!T[x].L&&!T[x].R){
        T[x].sum+=T[y].sum;
        return x;
    }
    T[x].L=merge(T[x].L,T[y].L);
    T[x].R=merge(T[x].R,T[y].R);
    pullup(x);return x;
}
inline void Link(int x,int y){
    x=find(x),y=find(y);
    if(x==y)return;
    fa[y]=x;
    rt[x]=merge(rt[x],rt[y]);
}
void init(){
    n=read(),m=read(),q=read();
    for(int i=1;i<=n;i++)
    h[i]=t[i]=read(),fa[i]=i;
    sort(t+1,t+n+1);
    for(int i=1;i<=n;i++){
        h[i]=lower_bound(t+1,t+n+1,h[i])-t;
        ins(rt[i],1,n,h[i]);
    }
    for(int i=1;i<=m;i++)
    e[i].u=read(),e[i].v=read(),e[i].w=read();
    sort(e+1,e+m+1);
    for(int i=1;i<=q;i++)
    a[i].u=read(),a[i].w=read(),a[i].k=read(),a[i].id=i;
    sort(a+1,a+q+1,cmpw);
}
void solve(){
    int now=1;
    for(int i=1;i<=q;i++){
        int lim=a[i].w,rk=a[i].k;
        while(e[now].w<=lim&&now<=m){
            Link(e[now].u,e[now].v);now++;
        }
        int u=find(a[i].u),siz=T[rt[u]].sum;
        if(siz<rk){
            a[i].ans=-1;continue;
        }
        else rk=siz-rk+1;
        a[i].ans=query(rt[u],1,n,rk);
    }
    sort(a+1,a+q+1,cmpid);
    for(int i=1;i<=q;i++)
    printf("%d\n",a[i].ans);
}
int main(){
    init();
    solve();
}
3545

技術分享圖片

[bzoj2733]永無鄉&&[bzoj3545]Peaks