Problem Description
daxia和suneast玩起來取石子游戲,現有n堆石子放成一排,每堆石子顆數爲a1,a2,...,an.
然後開始m輪遊戲,每輪遊戲之前,suneast先把第i堆的石子改成x顆,然後雙方開始在第j堆到第k堆之間進行取石子游戲.
取石子規則如下:
1. daxia先取,然後雙方輪流,每次取的數量不得超過該堆的一半;
2. 當輪到某一方,而其不能取到石子的時候,則判其爲負.
Input
測試包含多組數據.
每組數據第一行爲2個整數n(0<n<=100000),m(0<m<=100000).
接下來包含一行,共n個整數ai(0<ai<=1000000000).
接下來包含m行,每行4個整數i,x,j,k(1<=i,j,k<=n,0<x<=1000000000).
Output
每組數據輸出m行,如果爲daxia勝輸出"daxia",suneast勝則輸出"suneast".
Sample Input
Sample Output
Hint
第一輪改後(2 1 1),區間[1,3],daxia取完第一堆一顆獲勝
第二輪改後(3 1 1),區間[1,2],daxia和suneast各在第一堆取一顆後,suneast獲勝
第三輪改後(3 2 1),區間[3,3],daxia上來就沒得取,suneast獲勝
以前做過類似的題,不過那是一個堆,也是隻能取不超過一半石子,那題是打表找規律,這題也是。給你ai,它的sg值=x ,滿足a[i]=2^(y)*(2*x+1)
求出x後,[j,k]區間異或就是答案,但還要支持單點修改,那就是單點修改,區間求異或和,所以線段樹,樹狀數組都可以高效解決。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=2e5+10;
int a[maxn];
int bit[maxn];
int sum(int i){
int ans=0;
while(i>0){
ans^=bit[i];
i-=i&-i;
}
return ans;
}
void add(int i,int x,int xx){
while(i<maxn){
bit[i]=x^xx^bit[i];
i+=i&-i;
}
}
inline int ca(int x){
x++;
if(x==0)return 0;
while( !(x&1) ){
x>>=1;
}
return (x-1)/2;
}
int main()
{
//for(int i=0;i<100;i++)printf("%d\n",ca(i));
int n,m;
while(~scanf("%d%d",&n,&m)){
memset(bit,0,sizeof(bit));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]=ca(a[i]);
add(i,a[i],0);
}
int i,x,j,k;
for(int p=1;p<=m;p++){
scanf("%d%d%d%d",&i,&x,&j,&k);
x=ca(x);
add(i,x,a[i]);
a[i]=x;
int t1=min(j,k);int t2=max(k,j);
int ans=sum(t2)^sum(t1-1);
if(ans)printf("daxia\n");
else printf("suneast\n");
}
}
return 0;
}