Q - 昊昊爱运动 II
题意,区间长度N,N为1e5,运动种数为M,M<=100
Q次操作,Q<=1e5,每次可以把一个区间的运动都换成x,或者查询一个区间的运动种数
在放宽了时限和内存之后,bitset就直接搞过去了
之前因为卡的太紧,我就用两个long long模拟的bitset,另外线段树也没有存左右端点,是在更新和查询的过程中用形参来保存的
具体做法就是每个节点存一个bitset,表示颜色集合,更新的时候也是更新区间,lazy标记,然后查询的时候,就是子节点的bitset或一下就行,最后统计一下1的个数就是了
至于bitset的用法,百度一下就有很多详细解释了,大概也就是跟位运算相关的东西
坑点,貌似没有
代码:
#include <cstdio> #include <cstdlib> using namespace std; #define maxn 100005 #define lid (id<<1) #define rid ((id<<1)|1) #define ll long long int t; struct Node { ll num[2]; Node() { num[0] = 0; num[1] = 0; } Node(ll a, ll b) { num[0] = a, num[1] = b; } Node operator | (Node x) { Node y; y.num[0] = num[0] | x.num[0]; y.num[1] = num[1] | x.num[1]; return y; } }; struct segtree { ll num[2]; //int l, r; //bool lazy; }tr[maxn * 3]; bool lazy[maxn * 3]; inline int read() { int x = 0; char ch = getchar(); while (ch<'0' || ch>'9'){ ch = getchar(); } while (ch >= '0'&&ch <= '9'){ x = x * 10 + ch - '0'; ch = getchar(); } return x; } void push_down(int id, int nl,int nr) { if (lazy[id]) { if (nl < nr) { tr[lid].num[0] = tr[id].num[0]; tr[lid].num[1] = tr[id].num[1]; tr[rid].num[0] = tr[id].num[0]; tr[rid].num[1] = tr[id].num[1]; lazy[lid] = 1; lazy[rid] = 1; } lazy[id] = 0; } } void bulid(int id, int l, int r) { //tr[id].l = l; tr[id].r = r; if (l == r) { t = read(); if (t > 50) tr[id].num[1] = 1ll << (t - 50); else tr[id].num[0] = 1ll << t; return; } int mid = (l + r) >> 1; bulid(lid, l, mid); bulid(rid, mid + 1, r); tr[id].num[0] = tr[lid].num[0] | tr[rid].num[0]; tr[id].num[1] = tr[lid].num[1] | tr[rid].num[1]; } void update(int id, int nl, int nr, int l, int r, int idx, int v) { if (l == nl&&nr == r) { tr[id].num[0] = 0, tr[id].num[1] = 0; tr[id].num[idx] = 1ll << v; lazy[id] = 1; return; } push_down(id, nl, nr); int nmid = (nl + nr) >> 1; if (r <= nmid) update(lid, nl, nmid, l, r, idx, v); else if (l > nmid) update(rid, nmid + 1, nr, l, r, idx, v); else { update(lid, nl, nmid, l, nmid, idx, v); update(rid, nmid + 1, nr, nmid + 1, r, idx, v); } tr[id].num[0] = tr[lid].num[0] | tr[rid].num[0]; tr[id].num[1] = tr[lid].num[1] | tr[rid].num[1]; } Node query(int id, int nl, int nr, int l, int r) { if (lazy[id] || (l == nl&&r == nr)) { return Node(tr[id].num[0],tr[id].num[1]); } int mid = (nl + nr) >> 1; if (r <= mid) return query(lid, nl, mid, l, r); else if (l > mid) return query(rid, mid + 1, nr, l, r); else { return query(lid, nl, mid, l, mid) | query(rid, mid + 1, nr, mid + 1, r); } } int main() { //freopen("input.txt", "r", stdin); int N, M, Q, ans; int l, r, x; int pos, nn; //scanf("%d%d", &N, &M); N = read(); M = read(); /*for (int i = 1; i <= N; ++i) { //scanf("%d", &a[i]); a[i] = read(); }*/ bulid(1, 1, N); //scanf("%d", &Q); Q = read(); char c; for (int i = 0; i < Q; ++i) { while (c = getchar()) { if (c == 'Q' || c == 'M') break; } if (c == 'Q') { //scanf("%d%d", &l, &r); l = read(); r = read(); Node sum = query(1, 1, N, l, r); ans = 0; while (sum.num[0]) { if (sum.num[0] & 1) ++ans; sum.num[0] >>= 1; } while (sum.num[1]) { if (sum.num[1] & 1) ++ans; sum.num[1] >>= 1; } printf("%d\n",ans); } else if (c == 'M') { //scanf("%d%d%d", &l, &r, &x); l = read(); r = read(); x = read(); if (x > 50) { pos = 1, nn = x - 50; } else { pos = 0, nn = x; } update(1, 1, N, l, r, pos, nn); } } //system("pause"); //while (1); return 0; }