BZOJ4564 [Haoi2016]地图

仙人掌转成序列,然后莫队

仙人掌转成序列的方法是先tarjan找环,对于一个环上的点,如果是环根,那么这个环都属于其子仙人掌,如果不是环根,那么除了他自己这个环上都不是其子仙人掌,这样再dfs一次,对于一个点,优先走其出边里是其子仙人掌的部分,同时对于一个环,把不与环根相连的点的siz加到环根的siz里,这样仙人掌就转成了序列,一个子仙人掌对应的区间就是dfn[x]~dfn[x]+siz[x]-1

之后直接上莫队,用数据结构维护的话是n sqrtn logn的,T到爆,用和GTY的二逼妹子序列相同的方法,对权值分块,维护每块和每个点对答案的贡献,修改是单点修改,这样修改其所在块和这个位置,询问的时候变成sqrtn即可

数据好水啊,我在第二次dfs判这条出边和x是不是在一个环的时候没用tarjan的dfn而用了新dfs序都过了-_-

人生中第一次在BZOJ首A-_-

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 100010
#define MAXM 300010
#define MAXC 1000010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
struct vec{
    int to;
    int fro;
};
struct que{
    int cl;
    int v;
    int l;
    int r;
    int k;
    int num;
    friend bool operator <(que x,que y){
        return x.k!=y.k?x.k<y.k:x.r<y.r;
    }
};
int A[MAXN],a[MAXN];
int c;
que q[MAXN];
vec mp[MAXM];
int tai[MAXN],cnt=1;
int dfn[MAXN],DFN[MAXN],low[MAXN],ndf[MAXN],tim;
int n,m;
int siz[MAXN];
int ANS[2][MAXC];
int CNT[MAXC];
int Asiz;
int ans[MAXN];
inline void be(int x,int y){
    mp[++cnt].to=y;
    mp[cnt].fro=tai[x];
    tai[x]=cnt;
}
inline void bde(int x,int y){
    be(x,y);
    be(y,x);
}
void dfs(int x,int f){
    int i,y;
    DFN[x]=low[x]=++tim;
    ndf[tim]=x;
    for(i=tai[x];i;i=mp[i].fro){
        y=mp[i].to;
        if(i==(f^1)){
            continue ;
        }
        if(!DFN[y]){
            dfs(y,i);
            low[x]=min(low[x],low[y]);
        }else{
            low[x]=min(low[x],DFN[y]);
        }
    }
}
void dfs2(int x,int f){
    int i,y;
    siz[x]=1;
    dfn[x]=++tim;
    for(i=tai[x];i;i=mp[i].fro){
        y=mp[i].to;
        if(i==(f^1)){
            continue ;
        }
        if(!dfn[y]&&low[y]>=dfn[x]){
            dfs2(y,i);
            if(low[y]>dfn[x]){
                siz[x]+=siz[y];
            }
        }
    }
    for(i=tai[x];i;i=mp[i].fro){
        y=mp[i].to;
        if(i==(f^1)){
            continue ;
        }
        if(!dfn[y]&&low[y]<dfn[x]){
            dfs2(y,i);
        }
    }
    if(low[x]!=DFN[x]){
        siz[ndf[low[x]]]+=siz[x];
    }
}
int main(){
    int i,j,o,x,y;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++){
        scanf("%d",&A[i]);
        c=max(c,A[i]);
    }
    Asiz=sqrt(c);
    for(i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        bde(x,y);
    }
    dfs(1,0);
    tim=0;
    dfs2(1,0);
    for(i=1;i<=n;i++){
        a[dfn[i]]=A[i];
    }
    /*
    for(i=1;i<=n;i++){
        //<<DFN[i]<<' '<<low[i]<<endl;
    }
    for(i=1;i<=n;i++){
        //<<i<<'!'<<dfn[i]<<' '<<siz[i]<<endl;
    }
    //*/
    scanf("%d",&m);
    int SIZ=sqrt(n);
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&q[i].cl,&q[i].l,&q[i].v);
        q[i].r=dfn[q[i].l]+siz[q[i].l]-1;
        q[i].l=dfn[q[i].l];
        q[i].k=q[i].l/SIZ;
        q[i].num=i;
    }
    sort(q+1,q+m+1);
    int L=1,R=0;
    /*
    for(i=1;i<=n;i++){
        //<<a[i]<<' ';
    }
    //<<endl;
    */
    for(i=1;i<=m;i++){
         
        while(L>q[i].l){
            L--;
            //<<a[L]<<endl;
            x=(a[L]-1)/Asiz+1;
            if(CNT[a[L]]){
                ANS[CNT[a[L]]&1][x]--;
            }
            CNT[a[L]]++;
            ANS[CNT[a[L]]&1][x]++;
        }
        while(R<q[i].r){
            R++;
            x=(a[R]-1)/Asiz+1;
            //<<a[R]<<endl;
            if(CNT[a[R]]){
                ANS[CNT[a[R]]&1][x]--;
            }
            CNT[a[R]]++;
            ANS[CNT[a[R]]&1][x]++;
        }
        while(L<q[i].l){
            //<<a[L]<<endl;
            x=(a[L]-1)/Asiz+1;
            ANS[CNT[a[L]]&1][x]--;
            CNT[a[L]]--;
            if(CNT[a[L]]){
                ANS[CNT[a[L]]&1][x]++;
            }
            L++;
        }
        while(R>q[i].r){
            x=(a[R]-1)/Asiz+1;
            //<<a[R]<<endl;
            ANS[CNT[a[R]]&1][x]--;
            CNT[a[R]]--;
            if(CNT[a[R]]){
                ANS[CNT[a[R]]&1][x]++;
            }
            R--;
        }
        /*
        //<<L<<' '<<R<<endl;
        for(j=1;j<=(c-1)/Asiz+1;j++){
            //<<ANS[0][j]<<'!';
        }
        //<<endl;
        for(j=1;j<=(c-1)/Asiz+1;j++){
            //<<ANS[1][j]<<'!';
        }
        //<<endl;
        */
        x=(q[i].v-1)/Asiz+1;
        for(j=1;j<x;j++){
            ans[q[i].num]+=ANS[q[i].cl][j];
        }
        for(j=(x-1)*Asiz+1;j<=q[i].v;j++){
            if(CNT[j]&&((CNT[j]&1)==q[i].cl)){
                ans[q[i].num]++;
            }
        }
    }
    for(i=1;i<=m;i++){
        printf("%d\n",ans[i]);
    }
    return 0;
}
 
/*
7 8
1 2
2 3
3 4
4 1
3 5
5 6
6 7
7 3
 
5 6
2 1 6 7 7
1 2
1 3
2 4
4 5
4 5
1 3
3
0 3 2
0 3 1
0 1 7
 
*/</span>


你可能感兴趣的:(BZOJ4564 [Haoi2016]地图)