牛客网-湘潭大学校赛重现H题 (线段树 染色问题)
链接:https://www.nowcoder.com/acm/contest/105/H
来源:牛客网
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个操作,格式如题目所示。
输出描述:
对于每个2号操作,输出一个整数,表示查询的结果。
示例1
输入
10 10 1 1 2 0 1 3 4 1 2 1 4 1 5 6 2 2 1 6 1 7 8 1 2 3 8 1 8 10 3 2 1 10 2 3 8
输出
2 3 2 4 3
思路:
看到颜色<=60,摆明了用二进制。。写法跟poj2777差不多,只不过poj2777是覆盖颜色,这个是增加颜色。。
忘了 << 运算不支持long long范围。。找了半天错。。。直接用快速幂代替就好了
如果之前写过这种类型的题的话写起来就很简单了.
实现代码;
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<cmath> using namespace std; #define ll long long const ll M = 1e5+10; ll powl(ll n,ll m) { ll ans = 1; while(m > 0) { if(m & 1)ans = (ans * n); m = m >> 1; n = (n * n); } return ans; } ll n,w,e; ll color[M*4],lazy[M*4]; void pushup(ll rt){ color[rt] = color[rt*2]|color[rt*2+1]; } void build(ll l,ll r,ll rt){ if(l==r){ color[rt] = 0; return ; } ll m = (l+r)/2; build(l,m,rt*2); build(m+1,r,rt*2+1); pushup(rt); } void pushdown(ll rt){ if(lazy[rt]){ lazy[rt*2] |= lazy[rt]; lazy[rt*2+1] |= lazy[rt]; color[rt*2] |= lazy[rt*2]; color[rt*2+1] |= lazy[rt*2+1]; lazy[rt] = 0; } } void update(ll L,ll R,ll l,ll r,ll x,ll rt){ if(L<=l&&r<=R){ lazy[rt] |= powl(2,x-1); color[rt] |= powl(2,x-1); return ; } pushdown(rt); ll m = (l+r)/2; if(L<=m) update(L,R,l,m,x,rt*2); if(R>m) update(L,R,m+1,r,x,rt*2+1); pushup(rt); } ll query(ll L,ll R,ll l,ll r,ll rt){ if(L<=l&&r<=R){ return color[rt]; } ll ans1=0,ans2=0,ans; ll m = (l+r)/2; pushdown(rt); if(L<=m) ans1+=query(L,R,l,m,rt*2); if(R>m) ans2+=query(L,R,m+1,r,rt*2+1); ans = ans1|ans2; return ans; } void getsum(ll x){ ll ans = 0; while(x){ if(x%2==1) ans++; x/=2; } printf("%lld\n",ans); } int main() { ll L,R,x; int c; while(scanf("%lld%lld",&n,&w)!=EOF){ memset(lazy,0,sizeof(lazy)); build(1,n,1); while(w--){ scanf("%lld",&c); if(c==1){ scanf("%lld%lld%lld",&L,&R,&x); if(L>R) swap(L,R); x++; update(L,R,1,n,x,1); } else{ scanf("%lld%lld",&L,&R); if(L>R) swap(L,R); ll cnt = query(L,R,1,n,1); //cout<<cnt<<endl; getsum(cnt); } } } return 0; }