JZOJ 5832. 【省选模拟8.20】Emotional Flutter
中二少年cenbo幻想自己有Eternal Feather。他认为自己的走的每一步都是一次Emotional Flutter。
现在cenbo要走过一条斑马线,斑马线是由n条交替的黑条和白条构成的,第一条是黑条。
cenbo脚的长度是s。cenbo要求在走的过程中,他脚的任何一部分都不能碰到象征邪恶的黑条。
第一条之前和第n条之后的部分都是白色的,cenbo可以任意选择第一条之前的位置出发。
但出发位置一旦选定,之后cenbo的每一步的长度都必须是k。
请你判断cenbo有没有可能在不碰到黑条的情况下通过斑马线,即走到第n条之后。
30%的数据,n<=1300;
50%的数据,n<=22000;
100%的数据,2<=n<=500000, 1<=s<k<=10^9, 1<=A_i<=10^9, 1<=t<=10。
一道noip大概D1的略难于T1,但比T2简单的小水题…… 然后我成功的因为某个低级错误导致爆零
看到题后,看了一下$o(n^2)$的部分分,于是很容易的想出一个可以通过该测试点的暴力:如果最终有解,那么一定是存在一种脚后跟踩到一个白块的左侧,或者脚尖踩到一个白块的右侧的情况,于是可以暴力枚举以哪种方式踩在哪个白块上,然后再计算开始位置并$O(n)$的判断是否不会踩到黑块上
由于这个看起来如果要写的话十分令人不想写,于是激发我们去想一波正解
目前的瓶颈在于如果快速判断一种方案是否合法,不妨换个思路:假设当前枚举的脚的位置是$[x,y]$,那么可以踩到的地方可以写做$[x+kt,y+ky]$的形式,其中$t$是整数变量
观察这个式子,发现就是在模$k$意义下的一段区间(也可能是两端),因此将所有的黑块的范围模$k$后所得到的区间都填上$1$,相当于每次查询一段区间里是否存在$1$,这个做法多种多样,可以直接将线段搞出来后排序+合并+二分,也可以离散化后化作区间赋值+区间求和
注意判断$y-x+1 \ge k$的情况,此时在模$k$意义下是$[0,k-1]$ 这就是我爆零的原因 论大样例的重要性

1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 500000 + 10; 5 6 int s, k, n, a[N], tot; 7 8 ll sum[N], mod; 9 10 struct LN { 11 int l, r; 12 bool flag; 13 LN(int l = 0, int r = 0, int flag = 0) : l(l), r(r), flag(flag) {} 14 } ln[N * 2], tmp[N * 2]; 15 16 bool operator < (LN a, LN b) { 17 if(a.r == b.r) return a.l > b.l; 18 else return a.r < b.r; 19 } 20 21 pair<int, int> checkaft(int pos) { 22 ll l = sum[pos] - s + 1; 23 ll r = sum[pos]; 24 if(r - l + 1 >= k) l = 0, r = k - 1; 25 else l = (l % mod + mod) % mod, r = (r % mod + mod) % mod; 26 return make_pair(l, r); 27 } 28 29 pair<int, int> checkbef(int pos) { 30 ll l = sum[pos - 1] + 1; 31 ll r = sum[pos - 1] + s; 32 if(r - l + 1 >= k) l = 0, r = k - 1; 33 else l = (l % mod + mod) % mod, r = (r % mod + mod) % mod; 34 return make_pair(l, r); 35 } 36 37 int check(LN que) { 38 int l = que.l, r = que.r; 39 // printf("check: [%d, %d]\n", l, r); 40 if(ln[tot].r >= r) { 41 LN *it = lower_bound(ln + 1, ln + 1 + tot, LN(-1, r)); 42 LN p = *it; 43 if(p.l <= r) return 1; 44 else if(it != ln + 1) { 45 p = * (-- it); 46 if(l <= p.r && p.r <= r) return 1; 47 } 48 } else { 49 LN p = ln[tot]; 50 if(l <= p.r && p.r <= r) return 1; 51 } 52 return 0; 53 } 54 55 int check(pair<int, int> fafa) { 56 int l = fafa.first, r = fafa.second; 57 // printf("main: [%d, %d]\n", l, r); 58 if(l <= r) { 59 if(check(LN(l, r))) return 0; 60 } else { 61 if(check(LN(0, r)) || check(LN(l, k - 1))) return 0; 62 } 63 return 1; 64 } 65 66 void sol() { 67 scanf("%d%d%d", &s, &k, &n); 68 69 mod = k; 70 tot = 0; 71 72 for(int i = 1 ; i <= n ; ++ i) { 73 scanf("%d", &a[i]); 74 sum[i] = sum[i - 1] + a[i]; 75 if(i & 1) { 76 ll l = sum[i - 1] + 1; 77 ll r = sum[i]; 78 if(r - l + 1 >= k) l = 0, r = k - 1; 79 else l = (l % mod + mod) % mod, r = (r % mod + mod) % mod; 80 if(l <= r) { 81 ln[++ tot] = LN(l, r); 82 } else { 83 ln[++ tot] = LN(l, k - 1); 84 ln[++ tot] = LN(0, r); 85 } 86 } 87 } 88 89 sort(ln + 1, ln + 1 + tot); 90 for(int i = tot ; i >= 1 ; ) { 91 if(ln[i].flag) -- i; 92 else { 93 int pos = i; 94 while(pos - 1 >= 1 && ln[pos - 1].r >= ln[i].l && ln[pos - 1].l >= ln[i].l) { 95 ln[pos - 1].flag = 1; 96 -- pos; 97 } 98 if(pos == i) -- i; 99 else i = pos; 100 } 101 } 102 103 int ttt = 0; 104 for(int i = 1 ; i <= tot ; ++ i) { 105 if(ln[i].flag == 0) tmp[++ ttt] = ln[i]; 106 } 107 tot = ttt; 108 for(int i = 1 ; i <= tot ; ++ i) ln[i] = tmp[i]; 109 110 // for(int i = 1 ; i <= tot ; ++ i) { 111 // printf("[%d, %d]\n", ln[i].l, ln[i].r); 112 // } 113 114 for(int i = 2 ; i <= n ; i += 2) { 115 pair<int, int> bef = checkbef(i); 116 pair<int, int> aft = checkaft(i); 117 if(check(bef) || check(aft)) { 118 puts("TAK"); 119 return ; 120 } 121 } 122 123 ll l, r; 124 125 l = -s + 1, r = 0; 126 if(r - l + 1 >= k) l = 0, r = k - 1; 127 else l = (l % mod + mod) % mod, r = (r % mod + mod) % mod; 128 if(check(make_pair(l, r))) return puts("TAK"), void(); 129 130 l = sum[n] + 1, r = sum[n] + s; 131 if(r - l + 1 >= k) l = 0, r = k - 1; 132 else l = (l % mod + mod) % mod, r = (r % mod + mod) % mod; 133 if(check(make_pair(l, r))) return puts("TAK"), void(); 134 135 puts("NIE"); 136 } 137 138 int main() { 139 freopen("emotional.in", "r", stdin); 140 freopen("emotional.out", "w", stdout); 141 int T; scanf("%d", &T); 142 while(T --) sol(); 143 }