4810: [Ynoi2017]由乃的玉米田
Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 746 Solved: 368
[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
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
yumi
yuno
yuno
yumi
HINT
Source
【题解】
莫队 + bitset神奇的维护
若[l,r]内有i,则bitset[i] = 1
对于操作1:a - b = d ,等价于a = b + d,即将bitset左移d位(整体加d),与原bitset取并(与运算)即可
对于操作2:a + b = d,等价于(MAXN - )a = (MAXN - d) + b,维护bitset2,若有i则bitset2[MAXN - i] = 1,
之后同操作1
对于操作3:a * b = d,对d暴力分解因数即可
全是操作三复杂度可达n^2
但却能过。。
第一道莫队
细节: 关于区间变换的处理,先扩张,然后减小,少判断一些,用data存有多少个,不能单纯的改0或1
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <bitset> 7 #include <algorithm> 8 #define min(a, b) ((a) < (b) ? (a) : (b)) 9 #define max(a, b) ((a) > (b) ? (a) : (b)) 10 11 inline void swap(int &x, int &y) 12 { 13 int tmp = x;x = y;y = tmp; 14 } 15 16 inline void read(int &x) 17 { 18 x = 0;char ch = getchar(), c = ch; 19 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 20 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 21 if(c == '-')x = -x; 22 } 23 24 const int INF = 0x3f3f3f3f; 25 const int MAXN = 100001; 26 const int MAXNUM = 100001; 27 28 int n,m,num[MAXN + 10],l[MAXN + 10],r[MAXN + 10],block,size,ans[MAXN + 10],cnt[MAXN + 10],data1[MAXN + MAXN],data2[MAXN + MAXN]; 29 30 std::bitset<MAXNUM + MAXNUM> b1,b2; 31 32 struct Node 33 { 34 int l, r, kuai, id, d; 35 Node(int _l, int _r, int _kuai, int _id, int _d){d = _d;id = _id;l = _l;r = _r;kuai = _kuai;} 36 Node(){} 37 }node[MAXN << 1]; 38 39 bool cmp(int a, int b) 40 { 41 return node[a].kuai == node[b].kuai ? node[a].r < node[b].r : node[a].kuai < node[b].kuai; 42 } 43 44 int tiaoshi; 45 46 int main() 47 { 48 read(n);read(m); 49 for(register int i = 1;i <= n;++ i) 50 read(num[i]); 51 size = sqrt(n); 52 block = n/size; 53 if(block * size < n)++ block; 54 for(register int i = 1;i <= block;++ i) 55 l[i] = (i - 1) * block + 1, r[i] = min(i * block, n); 56 for(register int i = 1;i <= m;++ i) 57 { 58 read(node[i].id), read(node[i].l), read(node[i].r);read(node[i].d); 59 node[i].kuai = (node[i].l - 1)/size + 1; 60 cnt[i] = i; 61 } 62 std::sort(cnt + 1, cnt + 1 + m, cmp); 63 int now = 0, l = 1, r = n; 64 for(register int j = l;j <= r;++ j) 65 ++ data1[num[j]], ++ data2[MAXN - num[j]], b1[num[j]] = 1, b2[MAXN - num[j]] = 1; 66 for(register int p = 1;p <= m;++ p) 67 { 68 register int i = cnt[p]; 69 while(node[i].l > l) 70 { 71 -- data1[num[l]], -- data2[MAXN - num[l]]; 72 if(!data1[num[l]]) 73 b1[num[l]] = 0; 74 if(!data2[MAXN - num[l]]) 75 b2[MAXN - num[l]] = 0; 76 ++ l; 77 } 78 while(node[i].r < r) 79 { 80 -- data1[(num[r])], -- data2[MAXN - num[r]]; 81 if(!data1[num[r]]) 82 b1[num[r]] = 0; 83 if(!data2[MAXN - num[r]]) 84 b2[MAXN - num[r]] = 0; 85 -- r; 86 } 87 while(node[i].l < l) 88 { 89 -- l, ++ data1[num[l]], ++ data2[MAXN - num[l]]; 90 if(data1[num[l]] > 0) 91 b1[num[l]] = 1; 92 if(data2[MAXN - num[l]] > 0) 93 b2[MAXN - num[l]] = 1; 94 } 95 while(node[i].r > r) 96 { 97 ++ r, ++ data1[num[r]], ++ data2[MAXN - num[r]]; 98 if(data1[num[r]] > 0) 99 b1[num[r]] = 1; 100 if(data2[MAXN - num[r]] > 0) 101 b2[MAXN - num[r]] = 1; 102 } 103 if(node[i].id == 1) 104 { 105 if(((b1 >> node[i].d) & b1).any()) 106 ans[i] = 1; 107 } 108 else if(node[i].id == 2) 109 { 110 if(((b1 << (MAXN - node[i].d)) & b2).any()) 111 ans[i] = 1; 112 } 113 else 114 { 115 int tmp = sqrt(node[i].d); 116 if(node[i].d == 0) 117 { 118 if(b1.test(0)) 119 ans[i] = 1; 120 continue; 121 } 122 for(register int j = 1;j <= tmp;++ j) 123 { 124 if(node[i].d % j == 0) 125 { 126 if(b1.test(j) && b1.test(node[i].d/j)) 127 { 128 ans[i] = 1; 129 break; 130 } 131 } 132 } 133 } 134 } 135 for(register int i = 1;i <= m;++ i) 136 if(ans[i]) 137 printf("yuno "); 138 else 139 printf("yumi "); 140 return 0; 141 }