zoukankan      html  css  js  c++  java
  • # HDOJ Game[三维莫队]

    HDOJ Game[三维莫队]

    题意

    题链
    你有n堆石子,每堆石子有(a_i)个石子。游戏规则:Alice先选择一个大范围([L,R])区间内的石子,Bob选择一个子区间([l,r])内的石子最终进行游戏。每次至少取走某一堆的一个石子,至多全部取走,无法移动石子者输。Alice先手,双方足够聪明。问对Alice的每次选择([L_i,R_i]),Bob有多少种选择能让Alice必胜。
    还有修改操作,即交换相邻的两堆石子。

    思路

    • NIM博弈结论,区间异或和为0,先手必败
    • 问题转化为维护区间异或和为0的对数,对序列做前缀异或和,莫队维护前缀异或和出现的次数。
    • 带修改的莫队块大小为(n^{2/3})比较优秀
    • 对于每一个区间增加一个版本号,表示是第几次修改之后的,维护时,先将版本号更新到当前询问的,再将左右全金更新到当前询问的序列
    #include<bits/stdc++.h>
    #define N 100010
    #define INF 0x3f3f3f3f
    #define eps 1e-10
    // #define pi 3.141592653589793
    #define mod 998244353
    #define P 1000000007
    #define LL long long
    #define pb push_back
    #define fi first
    #define se second
    #define cl clear
    #define si size
    #define lb lower_bound
    #define ub upper_bound
    #define bug(x) cerr<<#x<<"      :   "<<x<<endl
    #define mem(x) memset(x,0,sizeof x)
    #define sc(x) scanf("%d",&x)
    #define scc(x,y) scanf("%d%d",&x,&y)
    #define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
    using namespace std;
    
     
    struct query{int l,r,e,id;} q[N];
    int n,k,m,tot,blocks,a[N],c[N];LL ans[N];
    inline bool cmp(query a,query b)
    {
        a.l/=blocks;a.r/=blocks;
        b.l/=blocks;b.r/=blocks;
        if(a.l==b.l)
            return a.r<b.r||(a.r==b.r&&a.e<b.e);
        return a.l<b.l;
    }
    int e[N];
    int num[1<<20];
    int main(){
        while(~scc(n,m)){
            blocks=pow(n,2.0/3);
            memset(num,0,sizeof num);
            for(int i=1;i<=n;i++) sc(a[i]),c[i]=c[i-1]^a[i];
            int cnt=0,tot=0;
            for(int i=1,op;i<=m;i++){
                sc(op);
                if (op==1){
                    tot++;
                    scc(q[tot].l,q[tot].r); q[tot].l--; q[tot].e=cnt; q[tot].id=tot;
                }else
                    sc(e[++cnt]);
            }
            sort(q+1,q+tot+1,cmp);
            int l=0,r=0,k=0; LL res=0; num[0]=1;
            for(int i=1;i<=tot;i++)                     
            {
                while(k<q[i].e){
                    k++;
                    int t=c[e[k]]^a[e[k]]^a[e[k]+1];
                    if(l<=e[k] && e[k]<=r){
                        res-=(--num[c[e[k]]]);
                        res+=num[t]++;
                    }
                    c[e[k]]=t;
                    swap(a[e[k]],a[e[k]+1]);
                }
                while(k>q[i].e){
                    int t=c[e[k]]^a[e[k]]^a[e[k]+1];
                    if(l<=e[k] && e[k]<=r){
                        res-=(--num[c[e[k]]]);
                        res+=num[t]++;
                    }
                    c[e[k]]=t;
                    swap(a[e[k]],a[e[k]+1]);
                    k--;
                }
                while(r<q[i].r){
                    r++;
                    res+=num[c[r]]++;//add
                }
                while(l>q[i].l){
                    l--;
                    res+=num[c[l]]++;//add
                }
                while(l<q[i].l){
                    res-=--num[c[l]];//del
                    l++;
                }
                while(r>q[i].r){
                    res-=--num[c[r]];//del
                    r--;
                }
                LL len=r-l;
                ans[q[i].id]=len*(len+1)/2-res;
            }
            for(int i=1;i<=tot;i++) printf("%lld
    ",ans[i]);
        }
    }
    
  • 相关阅读:
    什么是 FutureTask?使用 ExecutorService 启动任务?
    WeakHashMap 是怎么工作的?
    什么是 Executors 框架?
    什么是原子操作?在 Java Concurrency API 中有哪些原 子类(atomic classes)?
    Java 中是如何支持正则表达式操作的?
    JDBC 能否处理 Blob 和 Clob?
    Java 中你怎样唤醒一个阻塞的线程?
    Java Concurrency API 中的 Lock 接口(Lock interface) 是什么?对比同步它有什么优势?
    为什么我们调用 start()方法时会执行 run()方法,为什么 我们不能直接调用 run()方法?
    什么是线程组,为什么在 Java 中不推荐使用?
  • 原文地址:https://www.cnblogs.com/sstealer/p/12193814.html
Copyright © 2011-2022 走看看