1. 程式人生 > >[BZOJ4810][Ynoi2017]由乃的玉米田

[BZOJ4810][Ynoi2017]由乃的玉米田

Time Limit: 30 Sec Memory Limit: 256 MB

由乃在自己的農田邊散步,她突然發現田裡的一排玉米非常的不美。這排玉米一共有N株,它們的高度參差不齊。 由乃認為玉米田不美,所以她決定出個數據結構題

這個題是這樣的: 給你一個序列a,長度為n,有m次操作,每次詢問一個區間是否可以選出兩個數它們的差為x,或者詢問一個區間是否可以選出兩個數它們的和為x,或者詢問一個區間是否可以選出兩個數它們的乘積為x ,這三個操作分別為操作1,2,3選出的這兩個數可以是同一個位置的數

Input

第一行兩個數n,m 後面一行n個數表示aia_i 後面m行每行四個數opt, l, r, x opt表示這個是第幾種操作,l,r表示操作的區間,x表示這次操作的x 定義c為每次的x和ai中的最大值,a

i>=0a_i >= 0,每次的x>=n,m,c<=100000x>=n,m,c <= 100000

Output

對於每個詢問,如果可以,輸出yuno,否則輸出yumi

Sample Input

5 5
1 1 2 3 4
2 1 1 2
1 1 2 2
3 1 1 1
3 5 5 16
1 2 3 4

Sample Output

yuno
yumi
yuno
yuno
yumi

題解: 沒想到是分塊暴力吧23333,莫隊分塊,對於每個塊用兩個bitset分別儲存查詢區間的元素a

[i]a[i]的存在性(tp)和100000a[i]100000-a[i]的存在性(rtp)。對於詢問3,我們直接sqrt(x)sqrt(x)暴力(注意x==0的情況),對於詢問2,我們詢問集合tp和(rtp>>(100000-x-1))[即xa[i][L,R]x-a[i]∈[L,R]的集合]是否有交集,對於詢問2,我們詢問集合tp和(tp>>x) [即a[i]x[L,R]a[i]-x∈[L,R]的集合] 是否有交集。

複雜度O(n^2)但是常數很小的哦。

#include<bits/stdc++.h>
#define LiangJiaJun main #define N 100001 using namespace std; int n,m; bitset<N>rtp,tp,now; int cnt[100004]; int belong[100004]; struct ask{ int op,l,r,x,sit; }q[100004]; int a[100004]; bool ans[100004]; inline bool dex(ask A,ask B){ return belong[A.l]==belong[B.l]?A.r<B.r:belong[A.l]<belong[B.l]; } int solve(){ sort(q+1,q+m+1,dex); tp.reset(); rtp.reset(); int l=0,r=0; for(int i=1;i<=m;i++){ while(r<q[i].r){ ++r; if(!cnt[a[r]]){ tp.set(a[r]); rtp.set(N-a[r]-1); } cnt[a[r]]++; } while(l>q[i].l){ --l; if(!cnt[a[l]]){ tp.set(a[l]); rtp.set(N-a[l]-1); } cnt[a[l]]++; } while(r>q[i].r){ if(cnt[a[r]]==1){ tp.reset(a[r]); rtp.reset(N-a[r]-1); } cnt[a[r]]--; r--; } while(l<q[i].l){ if(cnt[a[l]]==1){ tp.reset(a[l]); rtp.reset(N-a[l]-1); } cnt[a[l]]--; l++; } if(q[i].op==3){ if(q[i].x==0&&tp[0]){ ans[q[i].sit]=1; continue; } for(int j=1;j<=sqrt(q[i].x);j++){ if(q[i].x%j!=0)continue; if(tp[j]&&tp[q[i].x/j]){ ans[q[i].sit]=1; break; } } } if(q[i].op==2){ now=(tp&(rtp>>(N-q[i].x-1))); if(now.any())ans[q[i].sit]=1; } if(q[i].op==1){ now=(tp&(tp>>q[i].x)); if(now.any())ans[q[i].sit]=1; } } return 0; } int w33ha(){ memset(cnt,0,sizeof(cnt)); memset(ans,0,sizeof(ans)); int block=(int)sqrt(n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++)belong[i]=(i-1)/block+1; for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&q[i].op,&q[i].l,&q[i].r,&q[i].x); q[i].sit=i; } solve(); for(int i=1;i<=m;i++){ if(!ans[i])puts("yumi"); else puts("yuno"); } return 0; } int LiangJiaJun(){ while(scanf("%d%d",&n,&m)!=EOF)w33ha(); return 0; }