zoukankan      html  css  js  c++  java
  • Wannafly挑战赛16 #E 弹球弹弹弹 splay+基环树+各种思维

    链接:https://ac.nowcoder.com/acm/problem/16033
    来源:牛客网

    有n个位置,标号为1到n的整数,m次操作,第i次操作放置一个弹球在b[i] xor c[i-1]处,并询问b[i] xor c[i-1]处弹球个数c[i]
    每次操作后,在x处的弹球被弹到a[x],规定c[0]=0

    把球弹来弹去的位置关系刻画出来的话是一个基环树森林的结构.
    每个不在环里的点会逐渐走向环,最终循环地在环里不停的转.
    然后你发现如果查询不在环上的点可以用一个 $splay$ 来维护每个联通块中每一个 $dep[u]+time[u]$ 的 $dfs$ 序.
    其实就是对于每一条链都以连续区间插入,这样查询的时候是区间查询.
    然后对于环上的点如何查询什么时候到就自己 $yy$ 一下吧,这个我实在是想不起来了,细节多的要命.

    #include<bits/stdc++.h>   
    #include <unordered_map>
    using namespace std;  
    #define rg register
    #define O2 __attribute__((optimize("-O2")))
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
    const int maxn=500003;
    const int inf=10000000;
    void setIO(string s) {
        string in=s+".in";
        freopen(in.c_str(),"r",stdin);
        freopen("tt.out","w",stdout);
    }
    struct Splay {
        #define lson ch[x][0]
        #define rson ch[x][1]
        int cnt;
        int ch[maxn][2],siz[maxn],f[maxn],mn[maxn],mx[maxn],pos[maxn]; 
        O2 inline void init() {
            cnt=0,mx[0]=-inf,mn[0]=inf;                      
        }
        O2 inline int get(int x) {
            return ch[f[x]][1]==x;
        }
        O2 inline void pushup(int x) {     
            siz[x]=siz[lson]+siz[rson]+1;
            mx[x]=mn[x]=pos[x]; 
            mx[x]=max(mx[x],mx[rson]);
            mn[x]=min(mn[x],mn[lson]);
        }
        O2 inline void rotate(int x) {
            int old=f[x],fold=f[old],which=get(x);
            ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
            ch[x][which^1]=old,f[old]=x,f[x]=fold;
            if(fold) ch[fold][ch[fold][1]==old]=x;   
            pushup(old), pushup(x);
        }
        O2 inline void splay(int x,int &tar) {
            int u=f[tar],fa;
            for(;(fa=f[x])^u;rotate(x))
                if(f[fa]^u)
                    rotate(get(fa)==get(x)?fa:x);
            tar=x;
        }
        O2 void insert(int &x,int p,int ff) {
            if(!x) {
                x=++cnt,f[x]=ff,pos[x]=p;
                pushup(x);
                return;
            }
            insert(ch[x][p>pos[x]],p,x), pushup(x);                 
        }            
        O2 int query(int x,int l,int r) {    
            if(!x||mx[x]<l||mn[x]>r) return 0;
            if(mn[x]>=l&&mx[x]<=r) return siz[x];             
            int re=0;
            if(pos[x]>=l&&pos[x]<=r) ++re;
            return re+query(lson,l,r)+query(rson,l,r);  
        }
        #undef lson
        #undef rson
    }tr;  
    struct Graph { 
        int edges;
        int hd[maxn],to[maxn],nex[maxn];
        O2 inline void addedge(int u,int v) {
            nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
        }
    }G,V; 
    int oo[maxn];
    vector<int>mm[maxn<<1];
    vector<int>cir[maxn];
    unordered_map<int, vector<int> >ins[maxn]; 
    int n,m,id,tim;
    int idx[maxn],dep[maxn],dfn[maxn],st[maxn],ed[maxn],top[maxn],dis[maxn];       
    unordered_map<int,int>rt[maxn];      
    unordered_map<int,int>bu[maxn];
    namespace prepare {
        int du[maxn];
        queue<int>Q;
        O2 void dfs(int u) {
            cir[idx[u]].push_back(u);  
            for(rg int i=V.hd[u];i;i=V.nex[i])
            {
                int v=V.to[i];       
                if(du[v]&&!idx[v]) {
                    idx[v]=idx[u];
                    dfs(v);
                    break;
                }
            }
        }
        O2 inline void work() {
            for(rg int i=1;i<=V.edges;++i) ++du[V.to[i]];    
            for(rg int i=1;i<=n;++i) if(!du[i]) Q.push(i);   
            while(!Q.empty()) {
                int u=Q.front(); Q.pop(); 
                for(rg int i=V.hd[u];i;i=V.nex[i]) {
                    int v=V.to[i];    
                    --du[v];  
                    if(!du[v]) Q.push(v);
                }
            }
            for(rg int i=1;i<=n;++i) {
                if(!du[i]) continue;
                if(!idx[i]) idx[i]=++id, dfs(i);  
            }
        }
    };
    O2 void dfs(int u,int ff) {
        dep[u]=dep[ff]+1,st[u]=++tim,dfn[tim]=u;
        for(rg int i=G.hd[u];i;i=G.nex[i]) {
            int v=G.to[i];
            if(v==ff||idx[v]) continue;    
            top[v]=top[u],dfs(v,u);
        }
        ed[u]=tim;
    }
    O2 int main() {
        // setIO("input");
        n=rd(); 
        memset(oo, -1, sizeof(oo));  
        for(rg int i=1;i<=n;++i) {
            int x=rd();
            V.addedge(i,x);      // 基环树
            G.addedge(x,i);      // 建树
        }  
        prepare::work(), tr.init();
        for(rg int i=1;i<=id;++i)
            for(rg int j=0;j<cir[i].size();++j) {
                top[cir[i][j]]=cir[i][j],dep[0]=-1,dfs(cir[i][j], 0);           
                dis[cir[i][j]]=j;           
            }
        m=rd();
        int lastans=0;
        for(rg int i=0;i<m;++i) {
            int b,cur,cur_id,cur_siz;
            b=rd(), b^=lastans, lastans=0;      
            cur_id=idx[top[b]];
            cur_siz=cir[cur_id].size();  
            int x1 = (dis[top[b]] - (i%cur_siz) + cur_siz) % cur_siz;
            int x2 = dep[b]%cur_siz;       
            int tmp = (x1 - x2 + cur_siz) % cur_siz;                                
            ins[cur_id][i+dep[b]].push_back(tmp), mm[i+dep[b]].push_back(cur_id);
            for(rg int o=0;o<mm[i].size();++o) {
                int uu=mm[i][o];        
                if(oo[uu]!=i) {
                    oo[uu]=i;
                    for(rg int j=0;j<ins[uu][i].size();++j) bu[uu][ins[uu][i][j]]+=1;
                }
            }        
            if(idx[b]) lastans+=bu[cur_id][(dis[b]-(i%cur_siz)+cur_siz)%cur_siz]; 
            else {
                cur=dep[b]+i;         
                tr.insert(rt[cur_id][cur], st[b], 0) , tr.splay(tr.cnt, rt[cur_id][cur]);
                int a=tr.query(rt[cur_id][cur],st[b],ed[b]);
                lastans+=a;
            }
            printf("%d
    ",lastans);       
        }
        return 0;
    }
    

      

  • 相关阅读:
    快捷键打开远程桌面
    织梦Dedecms后台登陆密码忘记怎么办?
    Windows curl开启注意事项
    Composer教程
    composer.json和composer.lock有什么区别?
    Web.config 文件例子
    win10回收站右键有2个“CCleaner”怎么删除
    sublime快捷键
    Json 文件注意事项
    加入购物车流程
  • 原文地址:https://www.cnblogs.com/guangheli/p/11253499.html
Copyright © 2011-2022 走看看