給乙個長為n的序列a,每個數在0到v - 1之間,有m次操作。
操作1:每次詢問乙個區間中是否可以選出兩個下標的集合x,y,滿足:
1.x和y沒有交集
2.設集合x中有乙個元素是i,則其對集合x的貢獻是a[i] + 1,要求集合x的元素的總貢獻和集合y的元素的總貢獻相等如果可以選出這兩個集合,輸出 yuno否則輸出 yuki
操作2:修改乙個區間l,r之間的數,使得所有l <= i <= r,a[i] = a[i] * a[i] * a[i] % v ,即區間立方
n , m <= 100000 , v <= 1000
乍一看根本不會做。
網上說只要序列長度大於13則答案必然為yuno。證明:因為子集數量有2l
en種,而權值則最多只有le
n∗1000
種,解方程可得le
n=13 。
有了這個結論這題就好做了。
對於乙個長度不超過13的序列,顯然每個數的係數只有0,1,-1三種,我們只要通過折半搜尋來判斷是否有貢獻相同的子集即可。
至於區間開三次方,我們可以通過線段樹打標記和倍增來實現。設bz[i,j]表示i3
2j,預處理後便可以在o(log)的複雜度內得到乙個數。
複雜度o(n
∗37)
,有點虛但實際上跑得賊快。
#include
#include
#include
#include
#include
using
namespace
std;
const
int n=100005;
const
int m=15000;
int n,m,v,bz[1005][20],size[n*4],a[n],tot,t[n],f[20];
bool vis[n],flag;
int read()
while (ch>='0'&&ch<='9')
return x*f;
}void prework()
void ins(int d,int l,int r,int x,int y)
int mid=(l+r)/2;
ins(d*2,l,mid,x,min(y,mid));
ins(d*2+1,mid+1,r,max(x,mid+1),y);
}int query(int d,int l,int r,int x)
int get(int x)
void dfs1(int x,int y,int z,int n)
dfs1(x+1,y,z,n);
if (flag) return;
dfs1(x+1,y+f[x]+1,z+1,n);
if (flag) return;
dfs1(x+1,y-f[x]-1,z+1,n);
}void dfs2(int x,int y,int z,int n)
dfs2(x+1,y,z,n);
if (flag) return;
dfs2(x+1,y+f[x]+1,z+1,n);
if (flag) return;
dfs2(x+1,y-f[x]-1,z+1,n);
}bool solve(int n)
int main()
for (int j=l;j<=r;j++) f[j-l+1]=get(j);
if (solve(r-l+1)) puts("yuno");
else
puts("yuki");}}
return
0;}
BZOJ4810 Ynoi2017 由乃的玉公尺田
對每個區間維護一下這個區間每個數有沒有,用bitset壓一下,這個用莫隊跑出來,然後就能判加減合不合法了 乘的話根號列舉一下就行了 include include include include include include include include include include incl...
bzoj4810 Ynoi2017 由乃的玉公尺田
由乃在自己的農田邊散步,她突然發現田裡的一排玉公尺非常的不美。這排玉公尺一共有n株,它們的高度參差不齊。由乃認為玉公尺田不美,所以她決定出個資料結構題 這個題是這樣的 給你乙個序列a,長度為n,有m次操作,每次詢問乙個區間是否可以選出兩個數它們的差為x,或者詢問乙個區間是否可以選出兩個數它們的和為x...
Ynoi2017 舌尖上的由乃
維護區間加和區間第k小。n 100000 分塊,設塊大小為k相信大家都會o n k log 2 n 的查詢和o k 的修改。什麼你不會o k 的修改?歸併啊歸併啊。那麼平衡規劃一下k n logn 總複雜度o nn l ogn include include include define fo i,...