hdu 6183 Color it(变种线段树)

时间:2023-02-04 18:06:11



Color it

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 629    Accepted Submission(s): 167


Problem Description
Do you like painting? Little D doesn't like painting, especially messy color paintings. Now Little B is painting. To prevent him from drawing messy painting, Little D asks you to write a program to maintain following operations. The specific format of these operations is as follows.

0 : clear all the points.

1  x  y  c : add a point which color is  c at point  (x,y).

2  x  y1  y2 : count how many different colors in the square  (1,y1) and  (x,y2). That is to say, if there is a point  (a,b) colored  c, that  1ax and  y1by2, then the color  c should be counted.

3 : exit.
 

Input
The input contains many lines. 

Each line contains a operation. It may be '0', '1 x y c' (  1x,y106,0c50 ), '2 x y1 y2' ( 1x,y1,y2106 ) or '3'. 

x,y,c,y1,y2 are all integers.

Assume the last operation is 3 and it appears only once.

There are at most  150000 continuous operations of operation 1 and operation 2. 

There are at most  10 operation 0. 

 

Output
For each operation 2, output an integer means the answer .
 

Sample Input
 
 
0 1 1000000 1000000 50 1 1000000 999999 0 1 1000000 999999 0 1 1000000 1000000 49 2 1000000 1000000 1000000 2 1000000 1 1000000 0 1 1 1 1 2 1 1 2 1 1 2 2 2 1 1 2 1 2 2 2 2 1 1 2 1 2 1 3 2 2 1 2 2 10 1 2 2 10 2 2 0 1 1 1 1 2 1 1 1 1 1 2 1 2 1 1 2 1 2 2 1 2 1 1 2 1 2 1 1 2 2 1 2 2 10 1 2 2 10 2 2 3
 

Sample Output
 
 
2 3 1 2 2 3 3 1 1 1 1 1 1 1

题意:
一个空的坐标系,有④种操作:①1 x y c表示在(x, y)点染上颜色c;②2 X y1 y2表示查询在(1, y1)到(X, y2)范围内有多少种不同的颜色:

③0表示清屏;④3表示程序退出(0<=x, y<=1000000, 0<=c<=50)
主要就是前两个操作,因为颜色数量较少,所以给每种颜色建立一颗线段树然后暴力查找,但是又不能以整个坐标系建树,考虑到题目条件一定包含坐标横坐标1

那么就可以只建Y坐标轴包存离y轴最近的点的坐标

这题的操作也是骚的一逼,线段树和主席树的变种操作


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include <set>
#include <bits/stdc++.h>
using namespace std;
const int N = 200000+10;
typedef long long LL;
int rt[55], ls[N*20], rs[N*20], val[N*20], cnt;
void add(int &o,int x,int y,int l,int r)
{
    if(o==0)  o=++cnt,val[o]=x;
    if(val[o]==0||val[o]>x)  val[o]=x;
    if(l==r) return ;
    int mid=(l+r)/2;
    if(y<=mid) add(ls[o],x,y,l,mid);
    else add(rs[o],x,y,mid+1,r);
    return ;
}
int flag;
void query(int o,int X,int L,int R,int l,int r)
{
    if(o==0||flag) return ;
    if(l>=L&&r<=R)
    {
        if(val[o]<=X) flag=1;
        return ;
    }
    int mid=(l+r)/2;
    if(L<=mid) query(ls[o],X,L,R,l,mid);
    if(R>mid) query(rs[o],X,L,R,mid+1,r);
    return ;
}

int main()
{
    memset(rt,0,sizeof(rt));
    memset(ls,0,sizeof(ls));
    memset(rs,0,sizeof(rs));
    cnt=0;
    int q;
    while(scanf("%d", &q))
    {
        if(q==1)
        {
            int x, y, z;
            scanf("%d %d %d", &x, &y, &z);
            add(rt[z],x,y,1,1000000);
        }
        else if(q==2)
        {
            int x, y1, y2, ans=0;
            scanf("%d %d %d", &x, &y1, &y2);
            for(int i=0; i<=50; i++)
            {
                flag=0;
                query(rt[i],x,y1,y2,1,1000000);
                ans+=flag;
            }
            printf("%d\n",ans);
        }
        else if(q==0)
        {
            memset(rt,0,sizeof(rt));
            memset(ls,0,sizeof(ls));
            memset(rs,0,sizeof(rs));
            cnt=0;
        }
        else break ;
    }
    return 0;
}