【HDOJ6610】Game(序列带修莫队)

题意:有n堆石子,第n堆有a[i]个,A先选择一个范围【L,R】,B选择一个子区间【l,r】,之后照nim游戏的规则进行

现在有询问与操作

每次询问B在给定的【L,R】内有多少种子区间的取法使得A必胜

每次操作会交换第x堆和第x+1堆石头

0<=a[i]<=1e6,n,m<=1e5

思路:

 

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 //typedef pair<ll,ll>P;
 11 #define N  3000010
 12 #define M  100010
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pb push_back
 17 #define pi acos(-1)
 18 #define mem(a,b) memset(a,b,sizeof(a))
 19 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 20 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 21 #define lowbit(x) x&(-x)
 22 #define Rand (rand()*(1<<16)+rand())
 23 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 24 #define ls p<<1
 25 #define rs p<<1|1
 26 
 27 const int MOD=1e9+7,inv2=(MOD+1)/2;
 28       double eps=1e-4;
 29       int INF=0x7fffffff;
 30       int inf=1e9;
 31       int dx[4]={-1,1,0,0};
 32       int dy[4]={0,0,-1,1};
 33 
 34 struct Q
 35 {
 36     int l,r,cur,id;
 37 }q[M];
 38 
 39 struct P
 40 {
 41     int x,pre,now;
 42 }p[M];
 43 
 44 int a[M],b[M],v[M],cnt[N],pos[M];
 45 ll sum,ans[M];
 46 
 47 bool cmp(Q a,Q b)
 48 {
 49    return pos[a.l]<pos[b.l]
 50         ||pos[a.l]==pos[b.l]&&pos[a.r]<pos[b.r]
 51         ||pos[a.l]==pos[b.l]&&pos[a.r]==pos[b.r]&&a.cur<b.cur;
 52 }
 53 
 54 int read()
 55 {
 56    int v=0,f=1;
 57    char c=getchar();
 58    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 59    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 60    return v*f;
 61 }
 62 
 63 void go(int x)
 64 {
 65     if(v[x])
 66     {
 67          cnt[b[x]]--;
 68          sum-=cnt[b[x]];
 69     }
 70      else
 71      {
 72          sum+=cnt[b[x]];
 73          cnt[b[x]]++;
 74      }
 75     v[x]^=1;
 76 }
 77 
 78 void update(int x)
 79 {
 80     if(!x) return;
 81     if(v[x])
 82     {
 83         go(x);
 84         b[x]^=a[x];
 85         swap(a[x],a[x+1]);
 86         b[x]^=a[x];
 87         go(x);
 88     }
 89      else
 90      {
 91          b[x]^=a[x];
 92         swap(a[x],a[x+1]);
 93         b[x]^=a[x];
 94      }
 95 }
 96 
 97 int main()
 98 {
 99     int n,m;
100     while(scanf("%d%d",&n,&m)!=EOF)
101     {
102         mem(cnt,0);
103         mem(v,0);
104         mem(a,0);
105         mem(b,0);
106         int S=max(10,(int)pow(n,2.0/3));
107         a[1]=b[1]=0; pos[1]=0;
108         rep(i,2,n+1)
109         {
110             a[i]=read();
111             b[i]=b[i-1]^a[i];
112             pos[i]=(i-1)/S;
113         }
114         int l1=0,l2=0;
115         rep(i,1,m)
116         {
117             int op=read();
118             if(op==1)
119             {
120                 int x=read(),y=read();
121                 q[++l1].l=x;
122                 q[l1].r=y+1;
123                 q[l1].id=l1;
124                 q[l1].cur=l2;
125             }
126             else
127             {
128                 int x=read();
129                 p[++l2].x=x+1;
130             }
131 
132         }
133         sort(q+1,q+l1+1,cmp);
134         int L=1,R=0,T=0;
135         sum=0;
136         rep(i,1,l1)
137         {
138             while(T<q[i].cur)
139             {
140                 T++;
141                 update(p[T].x);
142             }
143 
144             while(T>q[i].cur)
145             {
146                 update(p[T].x);
147                 T--;
148             }
149 
150             while(L>q[i].l) go(--L);
151             while(L<q[i].l) go(L++);
152             while(R>q[i].r) go(R--);
153             while(R<q[i].r) go(++R);
154             ll len=R-L+1;
155             ans[q[i].id]=len*(len-1)/2-sum;
156         }
157         rep(i,1,l1) printf("%I64d\n",ans[i]);
158     }
159 
160     return 0;
161 }

 

posted on 2019-10-07 20:05  myx12345  阅读(147)  评论(0编辑  收藏  举报

导航