P1558 色板游戏 状压线段树
每次不同颜色覆盖一段区间,每次询问一段区间有多少种颜色
因为颜色数\(T\)很小,使用二进制表示状态当前区间有那些颜色,二进制第\(i\)位表示此区间是否含有\(i\)这种颜色,线段树合并信息时左右儿子信息或一下就好了。
scanf
读入char
炸了我好久,最后换成cin
就AC了
AC Code:
#include <iostream> #define MAXN 100010 #define sl (x<<1) #define sr (x<<1|1) #define LL long long using namespace std; int l,t,o; inline void m_swap(int &a, int &b){ int t=a; a=b; b=t; } struct nod{ int l, r; LL val, lazy; } tre[MAXN*4]; void push_up(int x){ tre[x].val = tre[sl].val|tre[sr].val; } void built(int x, int l, int r){ tre[x].l=l,tre[x].r=r; if(l==r){ tre[x].val=1; return; } int mid=(l+r)>>1; built(sl, l, mid); built(sr, mid+1, r); push_up(x); } void push_down(int x){ if(tre[x].lazy==0) return; tre[sl].val=tre[sr].val=tre[x].lazy; tre[sl].lazy=tre[sr].lazy=tre[x].lazy; tre[x].lazy=0; } void change(int x, int l, int r, LL val){ if(l<=tre[x].l&&tre[x].r<=r){ tre[x].val=val; tre[x].lazy=val; return; } push_down(x); int mid=(tre[x].l+tre[x].r)>>1; if(l<=mid) change(sl, l, r, val); if(r>mid) change(sr, l, r, val); push_up(x); } LL query(int x, int l, int r){ if(l<=tre[x].l&&tre[x].r<=r) return tre[x].val; push_down(x); int mid=(tre[x].l+tre[x].r)>>1; LL ans=0; if(l<=mid) ans|=query(sl, l, r); if(r>mid) ans|=query(sr, l, r); return ans; } int main() { ios::sync_with_stdio(0); cin>>l>>t>>o; built(1, 1, l); while(o--){ char opt;cin>>opt; if(opt=='C'){ int a,b,c;cin>>a>>b>>c; if(a>b) m_swap(a,b); LL val=(1<<(c-1)); change(1, a, b, val); }else{ int a,b;cin>>a>>b; if(a>b) m_swap(a,b); LL res=query(1, a, b); int ans=0; for(int i=0;i<=t-1;++i) if((1<<i)&res) ans++; cout<<ans<<endl; } } return 0; }
来源:https://www.cnblogs.com/santiego/p/10978456.html