昊昊喜欢运动
他 N 天内会参加 M 种运动(每种运动用一个 [1,m] 的整数表示)
现在有 Q 个操作,操作描述如下
输入两个数 N N, M M ( 1≤N≤105 , 1≤M≤100 )
输入 N 个数 ai ( ai∈[1,m] 表示在第i天昊昊做了第 ai 类型的运动;
输入一个数 Q ( 1≤Q≤105 );
输入 Q Q行 每行描述以下两种操作
M l r x
,表示昊昊把第 l 天到第 r 天的运动全部换成了 x ( x∈[1,m] Q l r
,表示昊昊想知道他第 对于所有的Q操作,每一行输出一个数 表示昊昊在第
l天到第 r 天一共做了多少种活动
Sample Input | Sample Output |
---|---|
5 3 1 2 3 2 3 4 Q 1 4 Q 2 4 M 5 5 2 Q 1 5 |
3 2 3 |
2016 UESTC Training for Data Structures Problem Q
每次把一个区间变为一个定值
线段树+延迟操作+bitset
延迟操作,在查询或者改造的时候再向下传并标记好
先用memset全部标记为false表示值没有传下去;
在建树的时候就要一次把标记改为true了
然后改造的时候重新标记为false, 向下传的时候把false改为true,然后false也传下去;
返回的时候维护
另外每个节点用bitset维护,
push_up的时候 Top[Ind]=Top[Ind<<1] | Top[(Ind<<1)+1]; //这样自然就把原来的Top[Ind]去掉了
复杂度 O(nlogn)
#include <iostream> #include <cstdio> #include <cstring> #include <bitset> using namespace std; const int maxn = 100000+8; bitset<101> Top[4*maxn]; bool Cover[4*maxn]; //lazy[maxn] bitset<101> findans; int size; void _Query(int a,int b,int l,int r,int Ind){ if(a <= l && b >= r) {findans |= Top[Ind]; return;} int mid = (l+r)>>1; if(!Cover[Ind]){Top[Ind<<1] = Top[Ind];Top[(Ind<<1)+1] = Top[Ind];Cover[Ind] = true;Cover[Ind<<1] = false;Cover[(Ind<<1)+1] = false;} if(a <= mid) { _Query(a, b, l, mid, Ind<<1);} if(b > mid) { _Query(a, b, mid+1,r,(Ind<<1)+1);} } void _Modify(int a,int b,int l,int r,int Ind, int d){ if(a <= l && b >= r) {Top[Ind].reset(); Top[Ind][d] = 1; Cover[Ind] = false; return;} int mid = (l+r)>>1; if(!Cover[Ind]){Top[Ind<<1] = Top[Ind];Top[(Ind<<1)+1] = Top[Ind];Cover[Ind] = true;Cover[Ind<<1] = false;Cover[(Ind<<1)+1] = false;} if(a <= mid) { _Modify(a, b, l, mid, Ind<<1, d);} if(b > mid) { _Modify(a, b, mid+1, r,(Ind<<1)+1, d);} Top[Ind]=Top[Ind<<1] | Top[(Ind<<1)+1]; //这样自然就把原来的Top[Ind]去掉了 } void _Build(int a,int l,int r,int Ind,int d){ if(l == r && l == a){ Top[Ind][d] = 1; Cover[Ind] = false; //cout<<Top[Ind]<<endl; return; } int mid = (l+r)>>1; if(a <= mid) _Build(a,l,mid,Ind<<1,d); else _Build(a,mid+1,r,(Ind<<1)+1,d); Top[Ind]=Top[Ind<<1] | Top[(Ind<<1)+1]; //这样自然就把原来的Top[Ind]去掉了 Cover[Ind] = true;//!!!!!!这里加了句就对了☺☺ ,不然样例都过不了,(因为初始化为 false 了)这个区间的bitset会被传下去 } void Query(int a,int b) {return _Query(a,b,1,size,1);} void Modify(int a,int b,int d){return _Modify(a,b,1,size,1,d);} void Build(int a,int d) {return _Build(a,1,size,1,d);} int main() { #ifdef LOCAL freopen("a.txt", "r", stdin); #endif // LOCAL memset(Top, 0, sizeof Top); memset(Cover, false, sizeof Cover); int n, m, q, val; scanf("%d%d", &n, &m); size = n; for(int i = 1; i <= n; i++){ scanf("%d", &val); Build(i, val); } char op; int l, r, x; scanf("%d", &q);getchar(); while(q--){ scanf("%c", &op);// printf("%c\n", op); if(op == 'M'){ scanf("%d%d%d", &l, &r, &x); Modify(l, r, x); } else { findans.reset(); scanf("%d%d", &l, &r); Query(l,r); printf("%d\n", int(findans.count())); } getchar(); } return 0; } /*关于bitset获得1的个数 // bitset::count #include <iostream> #include <string> #include <bitset> using namespace std; int main () { bitset<8> myset (string("10110011")); cout << "myset has " << int(myset.count()) << " ones "; cout << "and " << int(myset.size()-myset.count()) << " zeros.\n"; return 0; } //Output: //myset has 5 ones, and 3 zeros */