2016 UESTC Training for Data Structures Q - 昊昊爱运动 II 线段树+延迟操作+bitset

Q - 昊昊爱运动 II

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit  Status

昊昊喜欢运动

N 天内会参加 M 种运动(每种运动用一个 [1,m]  的整数表示)

现在有 Q 个操作,操作描述如下

  • 昊昊把第 l  天到第 r 天的运动全部换成了 x ( x[1,m] 
  • 问昊昊第 l  天到第 r 天参加了多少种不同的运动

Input

输入两个数 N N M M ( 1N105 1M100

输入 N 个数 ai ( ai[1,m]    表示在第i天昊昊做了第 ai 类型的运动;

输入一个数 Q ( 1Q105  );

输入 Q Q行 每行描述以下两种操作

  • 形如M l r x,表示昊昊把第 l  天到第 r 天的运动全部换成了 x ( x[1,m]      
  • 形如Q l r,表示昊昊想知道他第
    l
    天到第 r 天参加了多少种不同的运动

Output

对于所有的Q操作,每一行输出一个数 表示昊昊在第
l
天到第 r 天一共做了多少种活动

Sample input and output

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
 
 
 

Source

2016 UESTC Training for Data Structures  Problem Q

My Solution

每次把一个区间变为一个定值

线段树+延迟操作+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

*/

Thank you!
                                                                                                                                               ------from ProLights

你可能感兴趣的:(ACM,for,Data,Training,uestc,2016,structures,线段树+延迟操作+bitset)