链接:
https://www.nowcoder.com/acm/contest/105/H
来源:牛客网
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
n个桶按顺序排列,我们用1~n给桶标号。有两种操作:
1 l r c 区间[l,r]中的每个桶中都放入一个颜色为c的球 (1≤l,r ≤n,l≤r,0≤c≤60)
2 l r 查询区间[l,r]的桶中有多少种不同颜色的球 (1≤l,r ≤n,l≤r)
1 l r c 区间[l,r]中的每个桶中都放入一个颜色为c的球 (1≤l,r ≤n,l≤r,0≤c≤60)
2 l r 查询区间[l,r]的桶中有多少种不同颜色的球 (1≤l,r ≤n,l≤r)
输入描述:
有多组数据,对于每组数据: 第一行有两个整数n,m(1≤n,m≤100000) 接下来m行,代表m个操作,格式如题目所示。这题是本蒟蒻队打的第一场模拟比赛 当时我和队友对这题无奈 不过赛后我们学习了大神的思路 A了 现在再我学了线段树以后 改几行代码就能A 好开心
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
int n,m;
const int MAX_N = 100010;
long long s[MAX_N<<2],col[MAX_N<<2];
void up(int p){
s[p] = (s[p*2]|s[p*2+1]);
}
void build(int p,int l,int r){
if(l==r){
col[p] = 0;
s[p] = 0;
return;
}
int mid = (l+r)>>1;
build (p*2,l,mid);
build(p*2+1,mid+1,r);
up(p);
}
void down(int p,int l,int r){
if(col[p]){
col[p*2] |= col[p];
col[p*2+1]|=col[p];
s[p*2]|=col[p];
s[p*2+1]|=col[p];
col[p] = 0;
}
}
void change(int p,int l,int r,int x,int y,int c){
if(x<=l&&r<=y){
col[p] |= c;
s[p] |= c;
return;
}
down(p,l,r);
int mid = (l+r)>>1;
if(x<=mid) change(p*2,l,mid,x,y,c);
if(y>mid) change(p*2+1,mid+1,r,x,y,c);
up(p);
}
int query(int p,int l,int r,int x,int y){
if(x<=l&&r<=y){
return s[p];
}
int mid = (l+r)>>1,res1 = 0,res2=0,res;
down(p,l,r);
if(x<=mid) res1|=query(p*2,l,mid,x,y);
if(y>mid) res2|=query(p*2+1,mid+1,r,x,y);
res = res1|res2;
return res;
}
int main(){
int t;
scanf("%d%d",&n,&t);
build(1,1,n);
while(t--){
int a;
scanf("%d",&a);
if(a==1){
int b,c,d;
scanf("%d%d%d",&b,&c,&d);
if(b>c){
b=b+c;
c=b-c;
b=b-c;
}
change(1,1,n,b,c,1<<d);
}
else if(a==2){
int b,c;
scanf("%d%d",&b,&c);
if(b>c){
b=b+c;
c=b-c;
b=b-c;
}
int ans = 0;
int pre_s = query(1,1,n,b,c);
while(pre_s){
if(pre_s&1==1) ans++;
pre_s/=2;
}
printf("%d\n",ans);
}
}
return 0;
}