bzoj 4810 由乃的玉米田 - bitset - 莫队算法

由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美。这排玉米一共有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


  题目大意 (数据结构裸题不需要大意)。(这是由乃OI?)

  显然bitset(别问我怎么知道的)。

  然而考虑分块,MLE?所以果断否决掉。

  是有个基于分块有很省内存的算法?莫队啊,我们只需要2个bitset和一个cnt数组就好了。

  现在来考虑具体的操作。

  1)区间内是否存在两个数差为x。这个很简单,bitset一个基本的应用。bitset维护一个值域,然后将所有数都减去x(相当于将这个bitset右移x位),再看有没有数相等(新bitset按位与旧bitset得到的bitset是否存在某一位为1,调用它的函数any()就好了)

  2)区间内是否存在两个数和为x。考虑a + b = x,加法不是很好处理,就转化成减法,得到a - (-b) = x。因为bitset不支持负数下标,把大小增大常数又变大,所以考虑用2个bitset。新的bitset维护某一个上限加上-b后的值域。查询的时候我们希望将第一个bitset右移x位,显然负数位才有价值,但是右移溢出的比特位会被直接舍去。所以考虑向左移,把右移x后,没有溢出的部分全部删去。这样的话就左移(limit - x)位,在和第二个bitset进行按位与,然后判断是否存在某一位为1。

  3)还是bitset?想多了。。。Tag害死人啊。。值域只有1e5。是不是直接根号大暴力(枚举因子)就完事了?(然后我忘判因子了,就WA了几次)

Code

 1 /**
 2  * bzoj
 3  * Problem#4810
 4  * Accepted
 5  * Time:13672ms
 6  * Memory:4472
 7  */
 8 #include<bits/stdc++.h>
 9 using namespace std;
10 typedef bool boolean;
11
12 typedef class Query {
13     public:
14         int opt;
15         int l;
16         int r;
17         int x;
18         int lid;
19         int id;
20
21         Query():opt(opt), l(l), r(r), x(x), lid(lid) {        }
22
23         boolean operator < (Query b) const {
24             if(lid != b.lid)    return lid < b.lid;
25             return r < b.r;
26         }
27 }Query;
28
29 #define limit 100001
30 int n, m, cs;
31 int *arr;
32 bitset<100005> s, s1, rs;
33 Query* qs;
34 inline void init() {
35     scanf("%d%d", &n, &m);
36     arr = new int[(n + 1)];
37     qs = new Query[(m + 1)];
38     cs = sqrt(n + 0.5);
39     for(int i = 1; i <= n; i++)
40         scanf("%d", arr + i);
41     for(int i = 1; i <= m; i++) {
42         scanf("%d%d%d%d", &qs[i].opt, &qs[i].l, &qs[i].r, &qs[i].x);
43         qs[i].lid = qs[i].l / cs, qs[i].id = i;
44     }
45 }
46
47 boolean *res;
48 int cnt[100005];
49 inline void extends(int pos, int val) {
50     cnt[arr[pos]] += val;
51     if(cnt[arr[pos]] == 1)    s[arr[pos]] = 1, rs[limit - arr[pos]] = 1;
52     if(cnt[arr[pos]] == 0)    s[arr[pos]] = 0, rs[limit - arr[pos]] = 0;
53 }
54
55 inline void solve() {
56     res = new boolean[(m + 1)];
57     sort(qs + 1, qs + m + 1);
58     int mdzzl = 1, mdzzr = 0;
59     boolean aFlag = false;
60     for(int i = 1; i <= m; i++) {
61         while(mdzzr < qs[i].r)    extends(++mdzzr, 1);
62         while(mdzzr > qs[i].r)    extends(mdzzr--, -1);
63         while(mdzzl > qs[i].l)    extends(--mdzzl, 1);
64         while(mdzzl < qs[i].l)    extends(mdzzl++, -1);
65         switch(qs[i].opt) {
66             case 1:
67                 s1 = (s << qs[i].x) & s;
68                 res[qs[i].id] = s1.any();
69                 break;
70             case 2:
71                 s1 = (s << (limit - qs[i].x)) & rs;
72                 res[qs[i].id] = s1.any();
73                 break;
74             case 3:
75                 aFlag = false;
76                 for(int j = 1; j * j <= qs[i].x; j++)
77                     if((qs[i].x % j == 0) && s[j] && s[qs[i].x / j]) {
78                         aFlag = true;
79                         break;
80                     }
81                 res[qs[i].id] = aFlag;
82                 break;
83             default:
84                 break;
85         }
86     }
87     for(int i = 1; i <= m; i++)
88         puts((res[i]) ? ("yuno") : ("yumi"));
89 }
90
91 int main() {
92     init();
93     solve();
94     return 0;
95 }
时间: 2024-10-21 19:58:44

bzoj 4810 由乃的玉米田 - bitset - 莫队算法的相关文章

bzoj 2038 小Z的袜子(hose)(莫队算法)

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 11542  Solved: 5166[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命--具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两

BZOJ 1878:[SDOI2009]HH的项链(莫队算法)

http://www.lydsy.com/JudgeOnline/problem.php?id=1878 题意:…… 思路:比上题还简单很多.数字很小,开一个数组哈希记录出现次数(记得数组要开1e6),然后直接算就行了. 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 #define N 50

【BZOJ】3781: 小B的询问(莫队算法)

http://www.lydsy.com/JudgeOnline/problem.php?id=3781 还能不能再裸点.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> #include <set>

bzoj 2120: 数颜色(带修改的莫队算法)

2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MB Submit: 2908  Solved: 1130 [Submit][Status][Discuss] Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col.为了满足墨墨的要求,你知道你需

BZOJ 2589 Spoj 10707 Count on a tree II 强制在线莫队算法(TLE)

题目大意:给定一棵树,每个节点有一个颜色,多次询问某条路径上颜色数量,强制在线 正解是块状数组,强制在线莫队会TLE到死,想AC这道题的不用看了 如果朴素的跑树上莫队其实并不难- - 但是强制在线 因此我们可以考虑强制在线莫队算法 将树分成O(n^1/3)块,每块大小O(n^2/3) 记录每两块之间的答案.每种颜色的出现次数和哪些点被记录到了答案中 每次查询先找到两端点所在块的端点的答案,然后暴力用莫队转移即可 空间复杂度O(n^1/3)*O(n^1/3)*O(n)=O(n^5/3) 预处理时间

BZOJ 2038 小Z的袜子(hose) (莫队离线)

题目地址:BZOJ 2038 裸的莫队算法. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> #includ

luogu P4688 [Ynoi2016]掉进兔子洞 bitset 莫队

题目链接 luogu P4688 [Ynoi2016]掉进兔子洞 题解 莫队维护bitset区间交个数 代码 // luogu-judger-enable-o2 #include<cmath> #include<bitset> #include<cstdio> #include<cstring> #include<algorithm> inline int read() { int x = 0,f = 1; char c = getchar();

luogu3674 小清新人渣的本愿 (bitset+莫队)

对于加减,用bitset维护当前每个数有没有 对于乘,暴力枚举约数 然后莫队 复杂度$O(m(\sqrt{n}+\frac{c}{64}))$ 1 #include<bits/stdc++.h> 2 #define pa pair<ll,ll> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 using namespace std; 6 typedef long long ll; 7 const i

BZOJ 3594 方伯伯的玉米田

dp好想.bit的优化好想.还有细节: (1)从k->0,这样才不会被本身转移. (2)这个dp表示的是以i结尾的最长的长度,所以随时max. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,k,tab[5550][550],dp[10050][550],h[10050],mx=0,ans=0; in