bzoj4810 [Ynoi2017]由乃的玉米田 bitset优化+暴力+莫队

[Ynoi2017]由乃的玉米田

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 917  Solved: 447
[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

By 佚名提供

 

题解:一开始以为是数据结构题,然后想了好久,题目也有一个坑点,可以选两个同位置的数,就是可以选相同的数。

   然后对于乘法的话,根号枚举即可,对于加法减法怎么办,可以用bitset优化,因为值的数据范围不大,

   所以我们可以x-y=z,那么x这个bitset右移z位,判断一下,和原来有没有交即可,对于区间的话还是需要莫队一下的

   对于加法x+y=z,貌似可以向左移,但是这里转换了以下,换成c-y,然后,x右移 c-(c-y)=+y,所以就可以了,

   这样复杂度是呢n^2/32的,莫队是并列的不是嵌套。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<cstdio>
 5 #include<algorithm>
 6 #include<bitset>
 7 
 8 #define N 400007
 9 using namespace std;
10 inline int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
14     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 
18 int n,m,c,blo;
19 int a[N],b[N],bel[N],ans[N],num[N];
20 struct Node
21 {
22     int opt,l,r,x,id;
23     friend bool operator<(Node x,Node y)
24     {
25         if (bel[x.l]==bel[y.l]) return x.r<y.r;
26         else return bel[x.l]<bel[y.l];
27     }
28 }q[N];
29 bitset<200011>f,g,h;
30 
31 void add(int x)
32 {
33     num[a[x]]++;
34     if (num[a[x]]==1)
35     {
36         f[a[x]]=1;
37         g[b[x]]=1;
38     }
39 }
40 void del(int x)
41 {
42     num[a[x]]--;
43     if (num[a[x]]==0)
44     {
45         f[a[x]]=0;
46         g[b[x]]=0;
47     }
48 }
49 bool query(Node w)
50 {
51     if (w.opt==3)
52     {
53         int up=sqrt(w.x);
54         for (int i=1;i<=up;i++)
55             if (w.x%i==0) if (num[i]&&num[w.x/i]) return true;
56     }
57     else if (w.opt==2)
58     {
59         h=g;
60         h>>=(c-w.x);
61         h&=f;
62         if (h.count()) return true;
63     }
64     else
65     {
66         h=f;
67         h>>=w.x;
68         h&=f;
69         if (h.count()) return true;
70     }
71     return false;
72 }
73 void solve_modui()
74 {
75     int l=1,r=0;
76     for (int i=1;i<=m;i++)
77     {
78         for (;r<q[i].r;r++)add(r+1);
79         for (;r>q[i].r;r--)del(r);
80         for (;l<q[i].l;l++)del(l);
81         for (;l>q[i].l;l--)add(l-1);
82         ans[q[i].id]=query(q[i]);
83     }
84     for (int i=1;i<=m;i++)
85         if (ans[i]) puts("yuno");
86         else puts("yumi");
87 }
88 int main()
89 {
90     n=read(),m=read(),blo=2*sqrt(n),c=100007;
91     for (int i=1;i<=n;i++)
92         a[i]=read(),b[i]=c-a[i],bel[i]=(i-1)/blo+1;
93     for (int i=1;i<=m;i++)
94         q[i].opt=read(),q[i].l=read(),q[i].r=read(),q[i].x=read(),q[i].id=i;
95     sort(q+1,q+m+1);
96     solve_modui();
97 }

 

posted @ 2018-04-09 15:02  Kaiser-  阅读(215)  评论(0编辑  收藏  举报