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;
}