Color it【HDU-6183】【CDQ分治套线段树】

题目链接


  题目中有这样的三种操作:

  1. 清空
  2. 添加颜色进(x,y)这个点颜色c
  3. 查询(1,y1)到(x,y2)区间内有几种颜色

  一开始的时候我直接写了个二维主席树,但是就是RE过不去,但是开大点就会TLE了,所以实在没法,只能想别的办法来做。

  这里的突破口还是在这个“1”上面,我们其实可以看作是查询一个前缀和的形式,但是限制条件y的范围在[y1, y2]之间。

  所以,我的做法就是用CDQ分治来处理时间和x轴前缀和上这样一个问题,然后呢,我们可以开一个线段树来维护对应时间戳上我们处理到的y轴上的信息,因为保证了x的升序,所以保证了在区间内的y一定是会被包含在里面的。

  那么,我们对应上时间戳,岂不就可以推到CDQ分治上去了嘛。

  但是,有个问题,就是在这里的“0”(清空),应该怎么办呢,我们可以将它考虑成为多组输入,上面已经输入的,我们直接进行操作,然后对于下面的我们再进行分开考虑,所以最后结束的时候也不要忘记再处理一遍。

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 3e5 + 7;
int tot;
ull ans[maxN] = {0};
bool lazy[maxN << 2] = {false};
ull tree[maxN << 2] = {0};
int Lsan_Y[400017], cnt_y, _Ux, _Uy, need_out, re_tim[150017];
struct Question
{
    int op, x, y, c, tim;
    Question(int a=0, int b=0, int cc=0, int d=0, int f=0):op(a), x(b), y(cc), c(d), tim(f) {}
}qes[150017], cop[150017];
inline void pushup(int rt) { tree[rt] = tree[lsn] | tree[rsn]; }
inline void pushdown(int rt)
{
    if(lazy[rt])
    {
        tree[lsn] = tree[rsn] = 0;
        lazy[lsn] = lazy[rsn] = true;
        lazy[rt] = false;
    }
}
inline void update(int rt, int l, int r, int qx, int col)
{
    if(l == r)
    {
        tree[rt] |= (ull)1 << (ull)col;
        return;
    }
    pushdown(rt);
    int mid = HalF;
    if(qx <= mid) update(Lson, qx, col);
    else update(Rson, qx, col);
    pushup(rt);
}
inline ull query(int rt, int l, int r, int ql, int qr)
{
    if(ql <= l && qr >= r) return tree[rt];
    pushdown(rt);
    int mid = HalF;
    if(qr <= mid) return query(QL);
    else if(ql > mid) return query(QR);
    else return query(QL) | query(QR);
}
inline int Count_num(ull val)
{
    int cnt_num = 0;
    while(val)
    {
        cnt_num += val & (ull)1;
        val >>= (ull)1;
    }
    return cnt_num;
}
void CDQ(int l, int r)
{
    if(l == r) return;
    int ql = l, mid = (l + r) >> 1, qr = mid + 1; //mid = time_num
    for(int i=l; i<=r; i++)
    {
        if(qes[i].tim <= mid)
        {
            cop[ql++] = qes[i];
            if(qes[i].op == 1)
            {
                update(1, 1, _Uy, qes[i].y, qes[i].c);
            }
        }
        else
        {
            cop[qr++] = qes[i];
            if(qes[i].op == 2)
            {
                ans[qes[i].tim] |= query(1, 1, _Uy, qes[i].y, qes[i].c);
            }
        }
    }
    lazy[1] = true;
    for(int i=l; i<=r; i++) qes[i] = cop[i];
    CDQ(l, mid); CDQ(mid + 1, r);
}
inline bool cmp_x(Question e1, Question e2) { return e1.x == e2.x ? e1.op < e2.op : e1.x < e2.x; }
int Q;
inline void solve()
{
    sort(Lsan_Y + 1, Lsan_Y + cnt_y + 1);
    _Uy = (int)(unique(Lsan_Y + 1, Lsan_Y + cnt_y + 1) - Lsan_Y - 1);
    for(int i=1; i<=Q; i++)
    {
        qes[i].y = (int)(lower_bound(Lsan_Y + 1, Lsan_Y + _Uy + 1, qes[i].y) - Lsan_Y);
        if(qes[i].op == 2) qes[i].c = (int)(lower_bound(Lsan_Y + 1, Lsan_Y + _Uy + 1, qes[i].c) - Lsan_Y);
    }
    sort(qes + 1, qes + Q + 1, cmp_x);
    if(Q) CDQ(1, Q);
    for(int i=1; i<=need_out; i++) printf("%d\n", Count_num(ans[re_tim[i]]));
}
int main()
{
    int op; tot = 0; cnt_y = need_out = Q = 0; tree[0] = 0; lazy[1] = true;
    int x, y, c, y1, y2;
    while(scanf("%d", &op) && (op ^ 3))
    {
        if(!op) //clear
        {
            solve();
            Q = 0;
            cnt_y = need_out = 0;
        }
        else if(op == 1)    //add
        {
            ++Q; ans[Q] = 0;
            scanf("%d%d%d", &x, &y, &c);
            qes[Q] = Question(op, x, y, c, Q);
            Lsan_Y[++cnt_y] = y;
        }
        else    //query
        {
            ++Q; ans[Q] = 0;
            scanf("%d%d%d", &x, &y1, &y2);
            if(y1 > y2) swap(y1, y2);
            qes[Q] = Question(op, x, y1, y2, Q);
            Lsan_Y[++cnt_y] = y1; Lsan_Y[++cnt_y] = y2;
            re_tim[++need_out] = Q;
        }
    }
    solve();
    return 0;
}
发布了722 篇原创文章 · 获赞 891 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/103980622