题目链接:http://poj.org/problem?id=2777
题目意思:就是问你在询问的区间里有几种不同的颜色
思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数。这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了。。。。
代码核心处就在计数那儿。。。。其它部分都是模板。。。。。。
code:
<span style="font-size:18px;">#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #define L(u) u<<1 #define R(u) u<<1|1 using namespace std; const int MAXN=100100; bool vis[35]; int cnt; struct Node { int l,r; int color; }node[MAXN*4]; void build(int u,int l,int r) //建树 { node[u].l=l; node[u].r=r; node[u].color=1; if(l==r) { return ; } int m=(l+r)/2; build(L(u),l,m); build(R(u),m+1,r); } void pushdown(int u) { if(node[u].color>0) { node[L(u)].color=node[R(u)].color=node[u].color; } } void pushup(int u) { if(node[L(u)].color==node[R(u)].color) { node[u].color=node[L(u)].color; } else { node[u].color=-1; } } void update(int l,int r,int v,int u) { if(l<=node[u].l&&node[u].r<=r) { node[u].color=v; return; } pushdown(u); int m=(node[u].l+node[u].r)/2; //if(l<=m) update(l,r,v,L(u)); //if(m<r) update(l,r,v,R(u)); if(r<=m) update(l,r,v,L(u)); else if(l>m) update(l,r,v,R(u)); else { update(l,m,v,L(u)); update(m+1,r,v,R(u)); } pushup(u); } void query(int l,int r,int u) { if(node[u].color>0) //为同一种颜色 { if(vis[node[u].color]==false) //这种颜色没有计算过 { cnt++; } vis[node[u].color]=true; //标记为计算过的 return ; } int m=(node[u].l+node[u].r)/2; //if(l<=m) query(l,r,L(u)); //if(m<r) query(l,r,R(u)); if(r<=m) query(l,r,L(u)); else if(l>m) query(l,r,R(u)); else { query(l,m,L(u)); query(m+1,r,R(u)); } } int main() { int n,t,q; while(scanf("%d%d%d",&n,&t,&q)==3) { build(1,1,n); while(q--) { char str[10]; scanf("%s",str); if(str[0]=='C') { int x,y,z; scanf("%d%d%d",&x,&y,&z); update(x,y,z,1); } else { int x,y; scanf("%d%d",&x,&y); memset(vis,0,sizeof(vis)); cnt=0; query(x,y,1); printf("%d\n",cnt); } } } return 0; } </span>
poj 2777 Count Color(线段树区间修改),布布扣,bubuko.com
时间: 2024-10-06 07:09:55