HDU 6291:对称数

做这个题做的我心态爆炸,昨天打第一场牛客网暑期ACM多校训练赛之前就在做这个题,一直tle,不知道为什么。。。搞的我打比赛的状态都不好了(掩盖一下我菜的事实)
今天准备再进行优化一下,看能不能过
把用vector存图改成数组式
加输入输出优化
然而还是tle,不可能啊,网上博客不也是这样吗,只不过LCA是不是离线和在线的问题,但不至于在线就tle吧,我又对比了其他博客的代码,思想差不多,应该没有问题,结果。。。。。
突然看到我的分块大小是pow(n,0.45)。。。难道是这个原因,昨天把sqrt(n)改成pow(n,0.45),想着会不会侥幸就过了,结果就忘记换回来了,所以换回sqrt(n)再交一发,就。。。。。。。过了

我的丑陋代码:

#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn=200000+100;

int deep[maxn],fa[maxn][20];
int unit,block,R[maxn];
int st[maxn],top;
int u,v;
struct Edge{

    int from,to;
    int next;
}edge[maxn*2];
int head[maxn],tot;
bool vis[maxn];
int ans[maxn];
int Ans[maxn];
int n,m;

void dfs(int u){

    for(int i=1;;i++){

        if((1<<i)>deep[u]) break;
        fa[u][i]=fa[fa[u][i-1]][i-1];
    }
    int bottom=top;
    for(int i=head[u];i!=-1;i=edge[i].next){

        Edge e=edge[i];
        int v=e.to;
        if(fa[v][0]) continue;
        deep[v]=deep[u]+1;
        fa[v][0]=u;
        dfs(v);
        if(top-bottom>=unit){

            block++;
            while(top!=bottom) R[st[top--]]=block;
        }
    }
    st[++top]=u;
}

inline int LCA(int x,int y){

    if(deep[x]<deep[y]) swap(x,y);
    int dis=deep[x]-deep[y];
    for(int i=0;;i++){

        if((1<<i)>dis) break;
        if((1<<i)&dis) x=fa[x][i];
    }
    if(x==y) return x;
    for(int i=20;i>=0;i--){

        if((1<<i)>deep[x]) continue;
        if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    }
    return fa[x][0];
}

struct Moq{

    int u,v;
    int id;
}moq[maxn];

inline bool cmp(Moq a,Moq b){

    return R[a.u]==R[b.u]?R[a.v]<R[b.v]:R[a.u]<R[b.u];
}

struct DataBlock{

    struct OneBlock{

        int l,r;
    }oneblock[500];
    int unit,block_num,n,num[maxn],R[maxn],sum[500];

    void init(){

        unit=sqrt(n);
        block_num=n/unit+(n%unit!=0);
        for(int i=1;i<=n;i++) R[i]=(i-1)/unit+1,num[i]=0;
        for(int i=1;i<=block_num;i++) oneblock[i].l=(i-1)*unit+1,oneblock[i].r=i*unit,sum[i]=0;
        oneblock[block_num].r=n;
    }

    inline void Add(int ind,int v){

        num[ind]+=v;
        if(num[ind]%2) sum[R[ind]]++;
        else sum[R[ind]]--;
    }
    inline int getMin(){

        for(int i=1;i<=block_num;i++){

            if(sum[i]!=(oneblock[i].r-oneblock[i].l+1)){

                for(int j=oneblock[i].l;j<=oneblock[i].r;j++){

                    if(num[j]%2==0) return j;
                }
            }
        }
    }
}Data;

inline Run(int ind){

    if(vis[ind]){

        Data.Add(ans[ind],-1);
        vis[ind]=0;
    }
    else{

        Data.Add(ans[ind],1);
        vis[ind]=1;
    } 
}

inline move(int x,int y){

    if(deep[x]<deep[y]) swap(x,y);
    while(deep[x]>deep[y]) Run(x),x=fa[x][0];
    while(x!=y) Run(x),Run(y),x=fa[x][0],y=fa[y][0];
}

void Mo(){

    for(int i=1;i<=m;i++){

        while(u!=moq[i].u) move(u,moq[i].u),u=moq[i].u;
        while(v!=moq[i].v) move(v,moq[i].v),v=moq[i].v;

        int lca=LCA(u,v);
        Run(lca);
        Ans[moq[i].id]=Data.getMin();
        Run(lca);
    }
}

void init(){

    u=v=1;
    block=top=tot=0;
    deep[1]=0;
    for(int i=1;i<=n;i++) fa[i][0]=0,vis[i]=false,head[i]=-1;
    fa[1][0]=-1;
}

inline void scan_d(int &res){

    res=0;
    char ch;
    ch=getchar();
    while(ch<'0' || ch>'9') ch=getchar();
    while(ch>='0' && ch<='9') res=res*10+(ch-'0'),ch=getchar();
}

inline void print_d(int res){

    if(res>9) print_d(res/10);
    putchar(res%10+'0');
}

int main(){

    int T;
    scan_d(T);
    while(T--){

        scan_d(n);
        scan_d(m);
        init();
        int Max=0;
        for(int i=1;i<=n;i++) scan_d(ans[i]),Max=max(Max,ans[i]);
        for(int i=1;i<n;i++){

            int a,b;
            scan_d(a);
            scan_d(b);

            edge[tot].from=a;
            edge[tot].to=b;
            edge[tot].next=head[a];
            head[a]=tot++;

            edge[tot].from=b;
            edge[tot].to=a;
            edge[tot].next=head[b];
            head[b]=tot++;
        }
        unit=sqrt(n);
        dfs(1);
        while(top) R[st[top--]]=block;
        Data.n=Max+1;
        Data.init();
        for(int i=1;i<=m;i++){

            scan_d(moq[i].u);
            scan_d(moq[i].v);
            moq[i].id=i;
        }
        sort(moq+1,moq+m+1,cmp);
        Mo();
        for(int i=1;i<=m;i++) print_d(Ans[i]),putchar('\n');
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/81129369