zoj 1610 线段树

用线段树进行区间赋值,最后将每个小segment的颜色求出来,再扫一遍判断连续的段数即可。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5
  6 const int N = 8001;
  7 int color[N];
  8 int ans[N];
  9
 10 struct Node
 11 {
 12     int l, r, c;
 13 } node[N << 2];
 14
 15 void build( int i, int l, int r )
 16 {
 17     node[i].l = l, node[i].r = r, node[i].c = -1;
 18     if ( l == r ) return ;
 19     int mid = ( l + r ) >> 1;
 20     build( i << 1, l, mid );
 21     build( i << 1 | 1, mid + 1, r );
 22 }
 23
 24 void pushdown( int i )
 25 {
 26     if ( node[i].c != -1 )
 27     {
 28         node[i << 1].c = node[i << 1 | 1].c = node[i].c;
 29         node[i].c = -1;
 30     }
 31 }
 32
 33 void update( int i, int l, int r, int c )
 34 {
 35     if ( node[i].l == l && node[i].r == r )
 36     {
 37         node[i].c = c;
 38         return ;
 39     }
 40     pushdown(i);
 41     int mid = ( node[i].l + node[i].r ) >> 1;
 42     if ( r <= mid )
 43     {
 44         update( i << 1, l, r, c );
 45     }
 46     else if ( l > mid )
 47     {
 48         update( i << 1 | 1, l, r, c );
 49     }
 50     else
 51     {
 52         update( i << 1, l, mid, c );
 53         update( i << 1 | 1, mid + 1, r, c );
 54     }
 55 }
 56
 57 void pushalldown( int i )
 58 {
 59     if ( node[i].l == node[i].r )
 60     {
 61         if ( node[i].c != -1 )
 62         {
 63             color[node[i].l] = node[i].c;
 64         }
 65         return ;
 66     }
 67     pushdown(i);
 68     pushalldown( i << 1 );
 69     pushalldown( i << 1 | 1 );
 70 }
 71
 72 int main ()
 73 {
 74     int n;
 75     while ( scanf("%d", &n) != EOF )
 76     {
 77         build( 1, 1, 8000 );
 78         for ( int i = 1; i <= n; i++ )
 79         {
 80             int x, y, z;
 81             scanf("%d%d%d", &x, &y, &z);
 82             update( 1, x + 1, y, z );
 83         }
 84         memset( color, -1, sizeof(color) );
 85         pushalldown(1);
 86         memset( ans, 0, sizeof(ans) );
 87         for ( int i = 1; i <= 8000; i++ )
 88         {
 89             if ( color[i] == -1 ) continue;
 90             ans[color[i]]++;
 91             while ( i + 1 <= 8000 && color[i] == color[i + 1] )
 92             {
 93                 i++;
 94             }
 95         }
 96         for ( int i = 0; i <= 8000; i++ )
 97         {
 98             if ( ans[i] )
 99             {
100                 printf("%d %d\n", i, ans[i]);
101             }
102         }
103         putchar(‘\n‘);
104     }
105     return 0;
106 }
时间: 2024-10-18 10:04:25

zoj 1610 线段树的相关文章

ZOJ 1610 线段树区间染色

给长度8000米的板,对其中区间染色,问最后能看到的颜色,和该颜色一共出现了几段 线段覆盖法 数据比较水   也可以暴力水过 线段树: #include "stdio.h" #include "string.h" struct node { int l,r,c; }data[40010]; int color[8011]; void build(int l,int r,int k) { int mid; data[k].l=l; data[k].r=r; data[

Count the Colors (zoj 1610 线段树 区间颜色覆盖)

Count the Colors Time Limit: 2 Seconds      Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones. Your task is counting the segments of different colors you can s

ZOJ 3635 线段树

线段树维护的是区间有多少个空位置,每次查询第X个空位置在哪,sum[rt]>=X就向左区间找,sum[rt]<X就向又区间找. #include <cstdio> #include <algorithm> #include <iostream> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int

zoj 3888 线段树 ***

卡n^2,用线段树降到nlogn 记录每个点上所覆盖线段的次小值,保证能有两条路径能走 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MO

ZOJ 3772 线段树

点击打开链接 题意:给一个数字序列,然后有m次询问,每次询问给了一个递推关系,然后输出询问的R的值 思路:n是100000,m是100000,然后来询问,就算不知道题意肯定也要向线段树这方面来想,而线段树的应用无非就是节点保存的信息嘛,这道题目要的是一段连续的递推式子,那么我们的节点就可以保存递推式,而这个式子也很好推,看代码应该可以看得懂,然后飞根节点保存的就是两个儿子的矩阵乘积后的矩阵,然后就是模版式的线段树,难点应该就是线段树的节点的内容嘛,而苦逼的我并不懂矩阵乘法的一些注意点,写完后无情

ZOJ 3911 线段树

题意:有N个数字,M个操作,然后回答每个Q开头的询问 操作形式: A val pos:在pos位置上+val Q l r:询问l~r之间有多少个质数 R val l r:把l~r之间的数字替换成val 分析:建成两棵树,一棵更新 原数列,一棵更新 质数序列(只有0,1) 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using name

HDU 1199 &amp;amp;&amp;amp; ZOJ 2301 线段树离散化

一段长度未知的线段.一种操作:a b c ,表示区间[a,b]涂为颜色C,w代表白色,b代表黑色,问终于的最长连续白色段,输出起始位置和终止位置 离散化处理.和寻常的离散化不同,须要把点化成线段.左闭右开,即对于一段区间[a.b],转化成区间[a,b+1) #include "stdio.h" #include "string.h" #include "algorithm" using namespace std; struct node { i

HDU 1199 &amp;&amp; ZOJ 2301 线段树离散化

一段长度未知的线段,一种操作:a b c ,表示区间[a,b]涂为颜色C,w代表白色,b代表黑色,问最终的最长连续白色段,输出起始位置和终止位置 离散化处理,和平常的离散化不同,需要把点化成线段,左闭右开,即对于一段区间[a,b],转化成区间[a,b+1) #include "stdio.h" #include "string.h" #include "algorithm" using namespace std; struct node { i

Zoj 3511 线段树

我们需要维护一个区间和表示各个区间剩下多少个点,每次切一个多边形的时候先算一下被切下来的多边形有多少条边(多少个顶点),然后把这些顶点抹掉即可. 但是会出现一个问题,如果被切下来的多边形还要继续被切,怎么破? 因为切的顺序是无关的,所以先将所有切的操作排序,先处理切下来小块的,然后处理大块的,就可以避免这个问题了. #include <cstdio> #include <cstring> #include <iostream> #include <map>