zoukankan      html  css  js  c++  java
  • ZOJ 1610 Count the Colors(区间染色)

    题目大意:多组数据,每组给一个n(1=<n<=8000),下面有n行,每行有l,r,color(1=<color<=8000),表示将l~r颜色变为color,最后求各种颜色(1~8000)所占区段数,如果所占区段为0则不用输出。

    解题思路:基本还是跟区间染色问题差不多,但要注意一些东西

    ①这里l,r指的是端点。比如

    3

    1 4 1

    1 2 2

    3 4 3

    这组数据最后输出结果为:

    1 1

    2 1

    3 1

    原因是还有[2,3]这一段颜色为1,处理办法是将更新函数写成(1,l+1,r,color)也就是左闭右开的形式,这样就可以使得中间的那块区间不背忽略。

    ②题目都没给总区间长度,所以无论查询还是建树,我们都默认用0~8000。

    ③关于查询各颜色所占区段数的问题,不可能直接通过线段树找到个颜色区段数,因为还要考虑两个子树是相邻的情况。所以可以通过使用一个vis[i]数组,记录各区间的颜色,最后只要简单处理一下就可以得到结果了。

     1 #include<cstring>
     2 #include<stdio.h>
     3 #include<iostream>
     4 #define LC(a) ((a<<1))
     5 #define RC(a) ((a<<1)+1)
     6 #define MID(a,b) ((a+b)>>1) 
     7 using namespace std;
     8 typedef long long ll;
     9 const int N=8e3*4;
    10 
    11 struct node{
    12     ll l,r;
    13     ll color;//颜色为-2表示混合色 
    14 }tree[N];
    15 
    16 ll ans[N];
    17 ll vis[N]; 
    18 //下推 
    19 void pushdown(ll p){
    20     tree[RC(p)].color=tree[LC(p)].color=tree[p].color;
    21 }
    22 //上推 
    23 void pushup(ll p){
    24     tree[p].color=(tree[LC(p)].color==tree[RC(p)].color?tree[LC(p)].color:-2);
    25 }
    26 
    27 void build(ll p,ll l,ll r){
    28     tree[p].l=l;
    29     tree[p].r=r;
    30     tree[p].color=-1;//初始化颜色因题意而定 
    31     if(l==r){
    32         return;
    33     }
    34     build(LC(p),l,MID(l,r));
    35     build(RC(p),MID(l,r)+1,r);
    36 }
    37 
    38 void update(ll p,ll l,ll r,ll color){
    39     if(r<tree[p].l||l>tree[p].r)
    40         return;
    41     if(tree[p].color==color)
    42         return;
    43     if(l<=tree[p].l&&r>=tree[p].r){
    44         tree[p].color=color;        
    45         return;
    46     }
    47     //**释放lazy标记 
    48     if(tree[p].color!=-2){
    49         pushdown(p);
    50     }
    51     update(LC(p),l,r,color);
    52     update(RC(p),l,r,color);
    53     pushup(p);
    54 }
    55 
    56 void query(ll p,ll l,ll r){
    57     if(r<tree[p].l||l>tree[p].r)
    58         return;
    59     
    60     //纯色,不用再找下去 
    61     if(tree[p].color!=-2){
    62         //**使用vis数组记录区间颜色 
    63         for(int i=tree[p].l;i<=tree[p].r;i++){
    64             vis[i]=tree[p].color;
    65         }
    66         return;
    67     }        
    68     query(LC(p),l,r);
    69     query(RC(p),l,r);
    70 }
    71 
    72 int main(){
    73     ios::sync_with_stdio(false);
    74     ll n;
    75     //注意是从0~n 
    76     while(cin>>n){
    77         build(1,0,8000);
    78         ll maxc=0;
    79         for(int i=1;i<=n;i++){
    80             ll l,r,color;
    81             cin>>l>>r>>color;
    82             maxc=max(maxc,color);
    83             update(1,l+1,r,color);
    84         }
    85         memset(ans,0,sizeof(ans));
    86         memset(vis,-1,sizeof(vis));
    87         query(1,1,8000);
    88         //处理vis数组,统计各区段数 
    89         for(int i=1;i<=8000;i++){
    90             if(vis[i]!=vis[i-1]&&vis[i]!=-1)
    91                 ans[vis[i]]++;
    92         }
    93         for(int i=0;i<=maxc;i++){
    94             if(ans[i])
    95                 cout<<i<<" "<<ans[i]<<endl;
    96         }
    97         cout<<endl;
    98     }
    99 }
  • 相关阅读:
    算法提高 道路和航路
    奇偶剪枝
    二分求值
    并查集--路径压缩
    Oracle数据库导入导出DMP文件
    Spring IoC的实现与思考(一)
    sql基础拾遗
    jquery事件函数的使用之focus
    Java动态代理之cglib
    Java se之动态代理
  • 原文地址:https://www.cnblogs.com/fu3638/p/7138774.html
Copyright © 2011-2022 走看看