ZOJ 1610 非点的区间修改及输出修改元素段 线段树+暴力查询

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 see at last.

Input



The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:

x1 x2 c

x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.

All the numbers are in the range [0, 8000], and they are all integers.

Input may contain several data set, process to the end of file.

Output



Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, they should be printed according to the color index.

If some color can't be seen, you shouldn't print it.

Print a blank line after every dataset.

Sample Input



5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
4
0 1 1
3 4 1
1 3 2
1 3 1
6
0 1 0
1 2 1
2 3 1
1 2 0
2 3 0
1 2 1

Sample Output



1 1
2 1
3 1

1 1

0 2
1 1

这道题很坑,为什么这么说,先讲讲坑

1.做了这么多区间查询及修改的题目,但是这道题虽然是区间修改,但是很特殊,比如让你修改[0,2]那你修改的区间时[0,1]和[1,2]这两个区间,而不是0,1,2这仨点。

2.数据给的数都是[0,8000]的范围,如果你建树的区间是[0,n],那就WA了,所以每次建树的时候都要建[0,8000]。

#include<iostream>
#include<bitset>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
#define lson id<<1,l,m
#define rson id<<1|1,m+1,r
const int M=8000+10;
ll n;
ll c[M<<2];
int a[M];
ll h,w;
//虽说是区间修改需要一个lazy数组,但是这一题比较特殊,你不需要取得最终最值,或者哪一个区间的值
//所以只需要对c数组进行标记处理,并将其往下推,我们要的是最底层的结果
void push(ll x)
{
    if(c[x]!=-1)
    {
        c[x<<1]=c[x<<1|1]=c[x];c[x]=-1;
    }
}
void build (int id,int l,int r)
{
    c[id]=-1;//不要直接放入到if语句里
    if(l==r){return;}
    ll m=(l+r)>>1;
    build(lson);
    build(rson);
    //push(id);
}
void update(int id,int l,int r,int L,int R,int p)
{
    if(L<=l&&R>=r){c[id]=p;return;}
    push(id);
    int m=(l+r)>>1;
    if(L<=m) update(lson,L,R,p);
    if(R>m) update(rson,L,R,p);
}
int query(ll id,ll l,ll r,ll p)//这算是单点(在这题中可以叫区间)查询吧
{
    if(l==r)return c[id];//这样递归到最底层,通过push函数就能将节点的值下推到树的最底层,这样就返回一个更新过的值
    ll m=(l+r)>>1;
    push(id);
    if(p<=m) return query(lson,p);
    else return query(rson,p);
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    while(cin>>n)
    {
       //memset(c,-1,sizeof c);
       memset(a,0,sizeof a);
       build(1,0,8000);
       while(n--)
       {
           int x,y,v;
           cin>>x>>y>>v;
           update(1,0,8000,x,y-1,v);//因为区间特殊,那我们就将右端点减小1,这样就又转化成
       }//点的修改了
       int pre=-1;
       for(int i=0;i<=8000;i++)
       {
           int k=query(1,0,8000,i);
           if(k!=-1&&k!=pre)//是求的段数,不是多少个区间,所以如果好几个区间的答案都是一样的,那就归为一段
            a[k]++;//k这种颜色就始终不加,直到颜色不同的时候
            pre=k;
       }
       for(int i=0;i<=8000;i++)
        if(a[i]) cout<<i<<" "<<a[i]<<endl;
       cout<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/c___c18/article/details/81780702
今日推荐