洛谷 P8569 [JRKSJ R6] 第七学区
好题,吹爆 JRKSJ!
考虑朴素的 做法。枚举第 位,需要计算所有极长连续的全 区间长度,答案为 。
然而这样不能通过。考虑分块,每 个元素为一块。
- 块内的子区间暴力枚举即可。这部分复杂度是 。
- 算块间的贡献,考虑算出当前块第 位第一次出现的位置 和最后一次出现的位置 。再维护一个 表示前面的块第 位最后一次出现的位置。考虑计算块内的前缀或序列 ,那么 就是 在块中第一次出现的位。这部分的时间复杂度为 。
- 算出来 和 ,考虑计算块间的贡献。枚举第 位,沿用暴力方法,右端点在当前块的全 区间数量为 。若当前块的所有元素的第 位都是 ,数量就是 。每次用 更新 即可。这部分的时间复杂度为
总时间复杂度为 ,实测 最优。
code
/* p_b_p_b txdy AThousandSuns txdy Wu_Ren txdy Appleblue17 txdy */ #include <bits/stdc++.h> #define pb push_back #define fst first #define scd second #define mems(a, x) memset((a), (x), sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ldb; typedef pair<ll, ll> pii; #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; namespace READ { ull Read() { char ch=getchar(); ull s=0; while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s; } ull tp[10005]; int l,r; ull g1,g2; void init(int &n) { int i,k; n=Read(),k=Read(),l=1; for(i=1;i<=k;i++) tp[i]=Read(); } ull read() { if(l>r) l=Read(),r=Read(),g1=Read(),g2=Read(); return tp[l++]*g1+g2; } } const int B = 17; int n, f[64], g[64], lst[64]; ull a[64], b[64], c[64], ans, sum; void solve() { READ::init(n); for (int l = 1; l <= n; l += B) { int r = min(l + B - 1, n), len = r - l + 1; sum += 1ULL * len * (len + 1) / 2; for (int i = l; i <= r; ++i) { a[i - l + 1] = READ::read(); } for (int i = 1; i <= len; ++i) { ull s = 0; for (int j = i; j <= len; ++j) { s |= a[j]; ans += s; } } mems(f, 0); mems(g, 0); b[0] = 0; for (int i = 1; i <= len; ++i) { b[i] = (b[i - 1] | a[i]); } for (int i = 1; i <= len; ++i) { ull val = (b[i] ^ b[i - 1]); while (val) { f[__builtin_ctzll(val)] = i + l - 1; val ^= (val & (-val)); } } b[len + 1] = 0; for (int i = len; i; --i) { b[i] = (b[i + 1] | a[i]); } for (int i = 1; i <= len; ++i) { ull val = (b[i] ^ b[i + 1]); while (val) { g[__builtin_ctzll(val)] = i + l - 1; val ^= (val & (-val)); } } for (int i = 0; i < 64; ++i) { if (f[i]) { c[i] += 1ULL * (f[i] - l) * (l - lst[i] - 1); lst[i] = g[i]; } else { c[i] += 1ULL * (r - l + 1) * (l - lst[i] - 1); } } } for (int i = 0; i < 64; ++i) { ans += (1ULL << i) * (1ULL * n * (n + 1) / 2 - sum - c[i]); } printf("%llu", ans); } int main() { int T = 1; // scanf("%d", &T); while (T--) { solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通