HDU6183 Color it (线段树动态开点)

题意:

一个1e6*1e6的棋盘,有两个操作:给(x,y)加上颜色c,或查找(1,y1)到(x,y2)内的颜色种类数量,最多有50种颜色

思路:

建立50颗线段树,对每个颜色的线段树,维护每个y坐标上x的最小值

但是这样会爆内存,于是动态开点即可

动态开点之后T了一发,就改了下查询的函数,只要有满足在矩形的该颜色,就全线return,果然快了好多

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 2e6+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);


int lc[maxn<<2];
int rc[maxn<<2];
int minv[maxn<<2];
int tot;
int root[55];
int build(){
    tot++;
    lc[tot]=rc[tot]=0;
    minv[tot]=mod;
    return tot;
}

void update(int p, int v, int l, int r, int &root){
    if(!root){
        root = build();
    }
    if(minv[root] > v) minv[root] = v;
    if(l==r)return;
    int mid = (l+r)/2;
    if(p <= mid)update(p,v,l,mid,lc[root]);
    if(p > mid)update(p,v,mid+1,r,rc[root]);
}
int flg;
int X;
void query(int ql, int qr, int l, int r, int root){
    if(!root||flg)return;
    if(ql <= l && r <= qr){
        if(minv[root]<=X)flg=1;
        return;
    }
    int mid = (l+r)/2;
    if(ql <= mid)query(ql, qr, l, mid, lc[root]);
    if(mid < qr) query(ql, qr, mid+1,r,rc[root]);
    return;
}
int main(){
    tot = 0;
    int op;

    while(scanf("%d", &op)){
        if(op==3)return 0;
        if(op==0){
            tot = 0;
            mem(root,0);
        }
        else if(op == 1){
            int x, y, c;
            scanf("%d %d %d", &x, &y, &c);
            if(!root[c]){
                root[c] = build();
            }
            update(y, x, 1, 1000000, root[c]);
        }
        else{
            int ans = 0;
            int x,y1,y2;
            scanf("%d %d %d", &x, &y1, &y2);
            X=x;
            for(int i = 0; i <= 50; i++){
                flg = 0;
                query(y1,y2,1,1000000,root[i]);
                //printf("-- %d %d
",i,tmp);
                if(flg)ans++;
            }
            printf("%d
",ans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10802731.html