【bzoj4810】【ynoi2018】由乃的玉米田

4810: [Ynoi2017]由乃的玉米田

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 1090  Solved: 524
[Submit][Status][Discuss]

Description

由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美。这排玉米一共有N株,它们的高度参差不齐。
由乃认为玉米田不美,所以她决定出个数据结构题
 
这个题是这样的:
给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是
否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1,2,3选出的这两个数可以是同一个位置的数

 

Input

第一行两个数n,m
后面一行n个数表示ai
后面m行每行四个数opt l r x
opt表示这个是第几种操作,l,r表示操作的区间,x表示这次操作的x
定义c为每次的x和ai中的最大值,ai >= 0,每次的x>=2n,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

HINT

 

Source

[Submit][Status][Discuss]

题解:
         //对于bitset来说,空间大一倍一意味着时间打一倍;
         //所以能小尽量小,(感谢bzoj的老爷机让我发现了这一点)
         对于一个区间,

         bitset维护x和最大值-x,可以通过左移和右移查询x+y和x-y

         根号枚举因子可以查询x*y;
         多个区间由于空间问题所以使用莫队优化空间,时间要付出一个根号;
         //注意bitset右移长度为负数的话似乎会出事。。。。。。
         $O(M\sqrt{M} + \frac{CM}{64} )$
         20181101

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<queue>
 6 #include<cmath>
 7 #include<vector>
 8 #include<stack>
 9 #include<map>
10 #include<bitset>
11 #define il inline 
12 #define rg register 
13 #define Run(i,l,r) for(rg int i=l;i<=r;i++)
14 #define Don(i,l,r) for(rg int i=l;i>=r;i--)
15 #define ll long long
16 #define ld long double
17 #define inf 0x3f3f3f3f
18 using namespace std;
19 const int N=100010 ;//, mx=100000;
20 il char gc(){
21     static char*p1,*p2,s[1000000];
22     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
23     return(p1==p2)?EOF:*p1++;
24 }
25 il int rd(){
26     int x=0; char c=gc();
27     while(c<'0'||c>'9')c=gc();
28     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
29     return x;
30 }
31 int n,m,a[N],num[N],ans[N],bl[N],mx;
32 struct data{
33     int l,r,op,x; int id;
34     il bool operator <(const data&A)const{
35         return bl[l]==bl[A.l]?r<A.r:l<A.l;
36     }
37 }Q[N];
38 bitset<N>f1,f2;
39 il void upd(int x,int y){
40     if(!num[x]&&y==1)f1.set(x),f2.set(mx-x);//f1[x]=f2[mx-x]=1;
41     num[x]+=y;
42     if(!num[x]&&y==-1)f1.reset(x),f2.reset(mx-x);//f1[x]=f2[mx-x]=0;
43 }
44 il bool ask(int op,int x){
45     if(op==1){
46         return ((f1>>x)&f1).count(); 
47     }else if(op==2){
48         return (f1&(f2>>(mx-x))).count();
49     }else {
50         for(int i=1;i*i<=x;i++){
51             if(x%i==0&&f1.test(i)&&f1.test(x/i)){
52                 return true;
53             }
54         }
55         return false;
56     }
57 }
58 int main(){
59     freopen("in.in","r",stdin);
60     freopen("out.out","w",stdout);
61     n=rd(); m=rd();
62     int u=2*sqrt(n+0.5);
63     Run(i,1,n)a[i]=rd(),bl[i]=i/u+1,mx=max(mx,a[i]);
64     Run(i,1,m){
65         Q[i].op=rd(); Q[i].l=rd(); Q[i].r=rd(); Q[i].x=rd(); Q[i].id=i; 
66         mx = max(Q[i].x,mx);
67     }
68     sort(Q+1,Q+m+1);
69     for(rg int i=1,l=1,r=0;i<=m;i++){
70         while(l>Q[i].l)upd(a[--l],1);
71         while(r<Q[i].r)upd(a[++r],1); 
72         while(l<Q[i].l)upd(a[l++],-1);
73         while(r>Q[i].r)upd(a[r--],-1);
74         ans[Q[i].id] = ask(Q[i].op,Q[i].x);
75     }
76     for(rg int i=1;i<=m;i++){
77         puts(ans[i]?"yuno":"yumi");
78     } 
79     return 0;
80 }//by tkys_Austin;
View Code

 

posted @ 2018-11-03 20:39  大米饼  阅读(243)  评论(0编辑  收藏  举报