• 【POJ2777】Count Color-线段树区间更新


    (本人本题完成于2016-7-21)

    题目大意:有一条长度为N的线段,被分成长度为1的N段,标号为1,2,...,N。现在要给这条线段上色,一共有T(不超过30)种颜色,标号为1,2,...,T,刚开始所有段的颜色都是1。有两种操作:1.C a b c:将区间(a,b)内的段的颜色改成c;2.P a b:询问区间(a,b)内的段有多少种不同的颜色。a可能大于b。你要做的就是根据询问给出答案。

    做法:建一棵线段树,除区间左右端点外再维护一个值n,如果n不为0,则表示该区间内的段的颜色均为n,如果n为0,则表示该区间内的段不只有一种颜色。建树时将所有n初始化为1。查询时,如果所查询到的区间的n值不为0,则将其统计入标记数组v中,并停止向下扩展。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,t,o,a,b,c,ans;
    char x;
    bool v[35]={0}; //v数组统计出现过的颜色
    struct node
    {
      int l,r;
      int n;
    }seg[300010];
    
    void buildtree(int no,int l,int r)
    {
      int mid=(l+r)/2;
      seg[no].l=l;seg[no].r=r;seg[no].n=1;
      if (l!=r)
      {
        buildtree(2*no,l,mid);
    	buildtree(2*no+1,mid+1,r);
      }
    }
    
    void col(int no,int s,int t,int c)
    {
      int mid=(seg[no].l+seg[no].r)/2;
      if (seg[no].l>=s&&seg[no].r<=t) seg[no].n=c; //lazy思想,n同时作为标记使用
      else
      {
        if (seg[no].n!=0) seg[2*no].n=seg[2*no+1].n=seg[no].n; //将标记下放
        if (s<=mid) col(2*no,s,t,c);
    	if (t>mid) col(2*no+1,s,t,c);
    	if (seg[2*no].n==seg[2*no+1].n) seg[no].n=seg[2*no].n;
    	else seg[no].n=0; //更新节点
      }
    }
    
    void query(int no,int s,int t)
    {
      int mid=(seg[no].l+seg[no].r)/2;
      if (seg[no].n!=0) v[seg[no].n]=1; //若seg[no].n不为0,将该颜色统计入v数组
      else
      {
        if (seg[no].n!=0) seg[2*no].n=seg[2*no+1].n=seg[no].n;
    	if (s<=mid) query(2*no,s,t);
    	if (t>mid) query(2*no+1,s,t);
    	if (seg[2*no].n==seg[2*no+1].n) seg[no].n=seg[2*no].n;
    	else seg[no].n=0;
      }
    }
    
    int main()
    {
      while(scanf("%d %d %d
    ",&n,&t,&o)!=EOF)
      {
        buildtree(1,1,n);
        for(int i=1;i<=o;i++)
        {
    	  scanf("%c",&x);
    	  if (x=='C')
    	  {
    	    scanf("%d %d %d
    ",&a,&b,&c);
    		if (a>b) {int t=a;a=b;b=t;} //a可能大于b,特殊处理
    		col(1,a,b,c); //上色:区间更新
    	  }
    	  if (x=='P')
    	  {
    	    scanf("%d %d
    ",&a,&b);
    		if (a>b) {int t=a;a=b;b=t;} //a可能大于b,特殊处理
                    memset(v,0,sizeof(v));
                    query(1,a,b); //查询
                    ans=0;
                    for(int j=1;j<=t;j++) if (v[j]) ans++; //统计出现过的不同颜色数目    
                    printf("%d
    ",ans);
              }
        }
      }
      return 0;
    }

  • 相关阅读:
    学习方法和阶段介绍 、 iOS界面开发引入 、 构造第一个App 、 视图控制器和视图 、 控件与事件 、 InterfaceBuilder
    Runtime 、 Block
    NSDictionary 、 NSMutableDictionary
    NSArray(二) 、 NSMutableArray 、 NSSet 、 NSMutableSet
    NSNumber 、 NSValue 、 日期处理 、 集合类 、 NSArray(一)
    (Foundation)NSObject 、 NSString 、 NSMutableString
    Objective-c---分类 、 扩展 、 ARC
    Objective-C--- 多态 、 协议
    关于Quartz2D方法小总结
    控制器之间的顺传与逆传
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9794017.html
Copyright © 2020-2023  润新知