_5011_ @ 2020-04-25 20:09:44
实在卡不动了。。。
TLE 95 分在线求卡。。。
#pragma GCC optimize("Ofast","-funroll-loops","-fdelete-null-pointer-checks")
#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline int qread() {
register char c = getchar();
register int x = 0, f = 1;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = (x << 3) + (x << 1) + c - 48;
c = getchar();
}
return x * f;
}
inline int Abs(const int& x) {return (x > 0 ? x : -x);}
inline int Max(const int& x, const int& y) {return (x > y ? x : y);}
inline int Min(const int& x, const int& y) {return (x < y ? x : y);}
const int S = 250;
struct Block {
pair <int, int> pre[35], suf[35], ans[35];
int pretop, suftop, anstop, mx[S + 5], val[S + 5], n, bl, br;
Block() {
pretop = suftop = n = bl = br = 0;
memset(mx, 0, sizeof(mx));
memset(val, 0, sizeof(val));
}
//O(sqrtnloga)
inline void Rebuild() {
pretop = 0;
memset(mx, 0xcf, sizeof(mx));
for (register int i = 1;i <= n;i++) {
pair <int, int> cur[35];
int curtop = 0;
for (register int j = 1;j <= pretop;j++) {
if (!(val[i] & (1 << pre[j].second))) cur[++curtop] = pre[j];
}
pretop = curtop;
for (register int j = 1;j <= pretop;j++) pre[j] = cur[j];
for (register int j = 0;j < 31;j++) {
if (val[i] & (1 << j)) pre[++pretop] = make_pair(i + bl - 1, j);
}
register int curval = 0;
for (register int j = pretop;j >= 1;j--) {
curval |= (1 << pre[j].second);
mx[i - pre[j].first + bl] = Max(mx[i - pre[j].first + bl], curval);
}
}
suftop = 0;
for (register int i = n;i >= 1;i--) {
pair <int, int> cur[35];
int curtop = 0;
for (register int j = 0;j < 31;j++) {
if (val[i] & (1 << j)) cur[++curtop] = make_pair(i + bl - 1, j);
}
for (register int j = 1;j <= suftop;j++) {
if (!(val[i] & (1 << suf[j].second))) cur[++curtop] = suf[j];
}
suftop = curtop;
for (register int j = 1;j <= suftop;j++) suf[j] = cur[j];
}
for (register int i = 1;i <= n;i++) mx[i] = Max(mx[i - 1], mx[i]);
}
};
Block blk[int(50000 / S) + 20];
int n, m, a[50005], pos[50005];
//O(loga)
inline void CalcAns(int i) {
blk[i].anstop = 0;
register int lst[35] = {0};
for (register int j = 1;j <= blk[i].pretop;j++) lst[blk[i].pre[j].second] = blk[i].pre[j].first;
for (register int j = 1;j <= blk[i - 1].anstop;j++) {
if (!lst[blk[i - 1].ans[j].second]) blk[i].ans[++blk[i].anstop] = blk[i - 1].ans[j];
}
for (register int j = 1;j <= blk[i].pretop;j++) blk[i].ans[++blk[i].anstop] = blk[i].pre[j];
}
//O(n)
inline void Read() {
n = qread(); m = qread();
for (register int i = 1;i <= n;i++) a[i] = qread(), pos[i] = (i - 1) / S + 1;
}
//O(n)
inline void Prefix() {
for (register int i = 1;i <= pos[n];i++) {
blk[i].bl = (i - 1) * S + 1;
blk[i].br = Min(i * S, n);
for (register int j = blk[i].bl;j <= blk[i].br;j++) blk[i].val[j - blk[i].bl + 1] = a[j];
blk[i].n = blk[i].br - blk[i].bl + 1;
blk[i].Rebuild();
}
for (register int i = 1;i <= pos[n];i++) CalcAns(i);
}
//O(m)
inline void Solve() {
while (m--) {
register int opt = qread();
if (opt == 1) {
register int i = qread();
blk[pos[i]].val[i - blk[pos[i]].bl + 1] = qread();
blk[pos[i]].Rebuild();
for (register int j = pos[i];j <= pos[n];j++) CalcAns(j);
} else {
register int k = qread(), ans = 0x3f3f3f3f;
for (register int i = 1;i <= pos[n];i++) {
while (blk[i].mx[Min(ans, blk[i].n + 1) - 1] >= k) ans = Min(ans, blk[i].n + 1) - 1;
// register int l = 0, r = blk[i].n + 1;
// while (l < r - 1) {
// register int mid = l + r >> 1;
// if (blk[i].mx[mid] >= k) r = mid;
// else l = mid;
// }
// if (r <= blk[i].n) ans = Min(ans, r);
}
for (register int i = 2;i <= pos[n];i++) {
register int lpnt = 1, rpnt = 1, orsum1 = 0, orsum2 = 0;
for (register int j = 1;j <= blk[i - 1].anstop;j++) orsum1 |= (1 << blk[i - 1].ans[j].second);
orsum2 |= (1 << blk[i].suf[1].second);
//printf("%d %d\n", blk[i - 1].ans[lpnt].first, blk[i].suf[rpnt].first);
while (rpnt <= blk[i].suftop && lpnt <= blk[i - 1].anstop) {
if (blk[i].suf[rpnt].first - blk[i].bl + 1 >= ans) break;
while ((orsum1 | orsum2) >= k && lpnt <= blk[i - 1].anstop) {
ans = Min(ans, blk[i].suf[rpnt].first - blk[i - 1].ans[lpnt].first + 1);
orsum1 ^= (1 << blk[i - 1].ans[lpnt].second);
lpnt++;
}
while ((orsum1 | orsum2) < k) {
rpnt++;
if (rpnt > blk[i].suftop) break;
orsum2 |= (1 << blk[i].suf[rpnt].second);
}
}
}
if (ans == 0x3f3f3f3f) puts("-1");
else printf("%d\n", ans);
}
}
}
int main() {
Read();
Prefix();
Solve();
#ifndef ONLINE_JUDGE
while (1);
#endif
return 0;
}
by 素质玩家孙1超 @ 2020-04-25 20:30:59
@momo5440 有、玄学。。。
by momo5440 @ 2020-04-25 20:32:19
不过确实是有效果的,有一次分块题我就是这样卡过去的
by spdarkle @ 2021-08-06 10:12:21
打一个快写模板
by spdarkle @ 2021-08-06 10:15:44
块大小为2的整次幂编译器会优化成一点点,很多都是,比如2,4这些编译成汇编之后和<<1,<<2的汇编代码一样,位运算一般比整数运算快,你可以试试把一些运算改成位运算,尽量少用除法和取模,能删括号尽量删
i++,j++全部改成++i,++j也会优化一点点
by DaydreamWarrior @ 2024-08-12 13:58:14
@spdarkle 你这个就是纯属于意淫了