• 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;
    }
  • 相关阅读:
    必须了解的经典排序算法整理
    浅谈Code Review
    NOIP2018提高组省一冲奖班模测训练(六)
    NOIP2018提高组省一冲奖班模测训练(五)
    NOIP2018提高组金牌训练营——动态规划专题
    poj 3074
    搜索中的剪枝
    bitset骚操作
    NOIP 2017 宝藏
    prim求最小生成树
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10802731.html
Copyright © 2020-2023  润新知