zoukankan      html  css  js  c++  java
  • Connections in Galaxy War ZOJ

    点权并查集的反向离线操作

    题目大意:有n个stars,每一个都一定的“颜值”。然后stars与stars之间可以相连,query c表示再与c相连的stars中,颜值比c高的,stars的标号,如果有多个, 输出最小那一个。destroy x y,表示将x和y这条边销毁掉。

    题解:并查集只能加边不能删边,所以我们可以倒着来,那么每个destroy就相当于join了。然后就是套上一个点权并查集(不会的自己学)。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N=1e5+7;
    const ll MAX=100000;
    ll Hash=1e4;
    map<ll,bool>mp;
    ll val[N];
    ll fa[N];
    bool mark[N];
    ll l[N],r[N];
    ll l1[N],r1[N];
    ll ans[N];
    
    ll find(ll x){
        return fa[x]==x? x:fa[x]=find(fa[x]);
    }
    
    void unite(ll x,ll y){
        ll fx=find(x);
        ll fy=find(y);
        if(val[fx]>val[fy]) fa[fy]=fx;
        else if(val[fx]<val[fy]) fa[fx]=fy;
        else if(fx>fy) fa[fx]=fy;
        else fa[fy]=fx;  
    }
    
    int main(){
        ll n,time=0;
        ios::sync_with_stdio(0);
        while(cin>>n){
            if(time++) printf("
    ");
            mp.clear();
            for(ll i=0;i<=100000;i++){
                fa[i]=i;
                mark[i]=0;
            }
            for(ll i=0;i<n;i++)   cin>>val[i];
            ll x;cin>>x;
            ll a,b;
            for(ll i=1;i<=x;i++){
                cin>>a>>b;
                if(a>b) swap(a,b);
                l1[i]=a;r1[i]=b;
            }
            ll m;cin>>m;
            string s;
            for(ll i=1;i<=m;i++){
                cin>>s;
                if(s=="destroy"){
                    cin>>a>>b;
                    mark[i]=1;
                    if(a>b) swap(a,b);
                    l[i]=a;r[i]=b;
                    mp[l[i]*Hash+r[i]]=1;//每个destroy用Hash记录一下
                }
                else cin>>l[i];
            }
            for(ll i=1;i<=x;i++){
                if(!mp[l1[i]*Hash+r1[i]]) {
                    unite(l1[i],r1[i]); 
                }
            }
            ll cnt=0;
            for(ll i=m;i>=1;i--){
                if(mark[i]) {
                    unite(l[i],r[i]);
                }
                else{
                    ll c=find(l[i]);
                    if(val[c]>val[l[i]]) ans[++cnt]=c;
                    else ans[++cnt]=-1;
                }
            }
            for(ll i=cnt;i>=1;i--)  printf("%lld
    ",ans[i]); 
        }
        return 0;
    }
  • 相关阅读:
    hdu 4002 Find the maximum
    hdu 2837 坑题。
    hdu 3123
    zoj Treasure Hunt IV
    hdu 2053 Switch Game 水题一枚,鉴定完毕
    poj 1430 Binary Stirling Numbers
    hdu 3037 Saving Beans
    hdu 3944 dp?
    南阳oj 求N!的二进制表示最低位的1的位置(从右向左数)。
    fzu 2171 防守阵地 II
  • 原文地址:https://www.cnblogs.com/Accepting/p/12660338.html
Copyright © 2011-2022 走看看