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

Description

要求你实现一个画板支持以下操作:

  1. 0 清空画板
  2. 1 x y c 在位置(x, y)添加颜色c
  3. 2 x y1 y2 求矩形区域(1, y1)到(x, y2)不同颜色的个数。
  4. 3 结束

\((1≤x,y,y1,y2≤10^6,0≤c≤50)\)

思路

每种颜色一棵线段树,搞51棵线段树。线段树保存区间[y1,y2]中最小的\(x_0\)。只要询问的x在区间[y1,y2]大于等于\(x_0\),说明这个区间至少包含这种颜色。
这题时间和空间都卡得很紧。要动态开点。其实很简单,就多个l,r数组存储左右子节点的编号。然后线段树实现尽可能优化,减少不必要的更新即可。

思考

这题貌似相同点的颜色不会被覆盖,写的时候没考虑。有时间考虑一下怎么做。

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <string>
#include <deque>
#include <cmath>
#include <iomanip>
#include <cctype>

#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define FILE freopen("..//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
#define FI freopen("..//data_generator//in.txt","r",stdin)
#define FO freopen("res.txt","w",stdout)
#define pb push_back
#define mp make_pair
#define seteps(N) fixed << setprecision(N)

typedef unsigned long long ull;
typedef long long ll;
using namespace std;

/*-----------------------------------------------------------------*/

#define INF 0x3f3f3f3f

const int N = 1e7 + 10;
const double eps = 1e5;
typedef pair<ll, ll> PII;


int root[100];
int minn[N];
int lc[N];
int rc[N];
int si;

void renew(int l, int r, int p, int val, int &rt) {
    if(!rt) {
        rt = ++si;
        minn[rt] = INF;
        lc[rt] = rc[rt] = 0;
    }
    minn[rt] = min(minn[rt], val);
    if(l == r) return ;
    int mid = (l + r) / 2;
    if(p <= mid) {
        renew(l, mid, p, val, lc[rt]);
    }
    else {
        renew(mid + 1, r, p, val, rc[rt]);
    }
} 


bool query(int l, int r, int L, int R, int val ,int rt) {
    if(!rt) return false;
    if(L <= l && R >= r) {
        return minn[rt] <= val;
    }
    if(minn[rt] > val) return false;
    int mid = (l + r) / 2;
    if(mid >= L)
        if(query(l, mid, L, R, val, lc[rt])) return true;
    if(mid < R) 
        if(query(mid + 1 ,r ,L, R,val, rc[rt])) return true;
    return false;
}


int main() {
    IOS;
    int op;
    while(cin >> op) {
        if(op == 3) break;
        if(op == 0) {
            si = 0;
            memset(root, 0, sizeof root);
        }
        else if(op == 1) {
            int x, y, c;
            cin >> x >> y >> c;
            renew(1, 1000000, y, x, root[c]);
        }
        else if(op == 2) {
            int x, y1, y2;
            cin >> x >> y1 >> y2;
            int ans = 0;
            for(int i = 0; i <= 50; i++) {
                if(query(1, 1000000, y1, y2, x, root[i])) ans++;
            }
            cout << ans << endl;
        }
    }
}
posted @ 2020-06-14 01:00  limil  阅读(190)  评论(0编辑  收藏  举报