cdoj 1259 线段树+bitset 区间更新/查询

Description

昊昊喜欢运动

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

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

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

Input

输入两个数NM (1N1051M100);

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

输入一个数Q(1Q105);

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

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

Output

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

Sample Input

5 3 
1 2 3 2 3 

Q 1 4 
Q 2 4 
M 5 5 2 
Q 1 5

Sample Output



3

题意:中文题意
 
题解:线段树+bitset
 bitset记录运动的种类 bitset的用法 姿势涨  
 bitset<110> sum 
 
 (sum.reset() 全部置为0 )
 (sum.count()计算为1的位数) 
 (sum[x]=1 第x位赋为1)
 坑点: 千万不要直接复制样例 直接复制会很坑 orzzzz
      getchar()的问题  re多次   太菜了...
                  
  1 /******************************
  2 code by drizzle
  3 blog: www.cnblogs.com/hsd-/
  4 ^ ^    ^ ^
  5  O      O
  6 ******************************/
  7 //#include<bits/stdc++.h>
  8 #include<iostream>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<cstdio>
 12 #include<bitset>
 13 //#define ll long long
 14 #define mod 1000000007
 15 #define PI acos(-1.0)
 16 using namespace std;
 17 struct node
 18 {
 19     int l,r;
 20     int add;
 21     bitset<110> sum;
 22 } tree[2000005];
 23 int n,m;
 24 int exm;
 25 int l1,r1,x;
 26 int q;
 27 char judge;
 28 void buildtree(int root,int left,int right)
 29 {
 30     tree[root].l=left;
 31     tree[root].r=right;
 32     tree[root].add=0;
 33     if(left==right)
 34     {
 35         tree[root].sum.reset();
 36         scanf("%d",&exm);
 37         tree[root].sum[exm]=1;
 38         return ;
 39     }
 40     int mid=(left+right)>>1;
 41     buildtree(root<<1,left,mid);
 42     buildtree(root<<1|1,mid+1,right);
 43     tree[root].sum=tree[root<<1].sum|tree[root<<1|1].sum;//按位或得到新的运动种类
 44 }
 45 void pushdown(int root)
 46 {
 47     if(tree[root].add==0)
 48         return ;
 49     tree[root<<1].sum.reset();
 50     tree[root<<1|1].sum.reset();
 51     tree[root<<1].sum[tree[root].add]=1;
 52     tree[root<<1|1].sum[tree[root].add]=1;
 53     tree[root<<1].add=tree[root].add;//注意延迟标记也要往下传
 54     tree[root<<1|1].add=tree[root].add;
 55     tree[root].add=0;
 56 }
 57 void updata(int root,int left,int right,int c)
 58 {
 59     if(tree[root].l==left&&tree[root].r==right)
 60     {
 61         tree[root].sum.reset();//全部置零
 62         tree[root].add=c;
 63         tree[root].sum[c]=1;//整个区间只有c运动
 64         return ;
 65     }
 66     pushdown(root);//lazy 延迟标记
 67     int mid=(tree[root].l+tree[root].r)>>1;
 68     if(right<=mid)
 69         updata(root<<1,left,right,c);
 70     else
 71     {
 72         if(left>mid)
 73             updata(root<<1|1,left,right,c);
 74         else
 75         {
 76             updata(root<<1,left,mid,c);
 77             updata(root<<1|1,mid+1,right,c);
 78         }
 79     }
 80     tree[root].sum=tree[root<<1].sum|tree[root<<1|1].sum;
 81 }
 82 bitset<110> query(int root,int left,int right)
 83 {
 84     if(tree[root].l==left&&tree[root].r==right)
 85     {
 86         return  tree[root].sum;
 87     }
 88     pushdown(root);
 89     int mid=(tree[root].l+tree[root].r)>>1;
 90     if(right<=mid)
 91         return query(root<<1,left,right);
 92     else
 93     {
 94         if(left>mid)
 95             return query(root<<1|1,left,right);
 96         else
 97             return query(root<<1,left,mid)|query(root<<1|1,mid+1,right);
 98     }
 99 }
100 int main()
101 {
102     while(scanf("%d %d",&n,&m)!=EOF)
103     {
104         buildtree(1,1,n);
105         scanf("%d",&q);
106         getchar();
107         for(int i=1; i<=q; i++)
108         {
109             scanf("%c",&judge);
110             if(judge=='Q')
111             {
112                 scanf("%d %d",&l1,&r1);
113                 printf("%d
",query(1,l1,r1).count());
114             }
115             else
116             {
117                 scanf("%d %d %d",&l1,&r1,&x);
118                 updata(1,l1,r1,x);
119             }
120             getchar();//坑点
121         }
122     }
123     return 0;
124 }
 
原文地址:https://www.cnblogs.com/hsd-/p/5713167.html