HDU - 6183 Color it(动态开点线段树/树状数组套动态开点线段树)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 6183 Color it(动态开点线段树/树状数组套动态开点线段树)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出一个二维平面坐标系,需要完成四种操作:

  1. 0:删除所有点
  2. 1 x   y   c x\\ y\\ c x y c:在点 ( x , y ) (x,y) (x,y) 处添加颜色 c c c
  3. 2 x   y 1   y 2 x\\ y1\\ y2 x y1 y2:查询左下角为 ( 1 , y 1 ) (1,y1) (1,y1) 右上角为 ( x , y 2 ) (x,y2) (x,y2) 矩阵内有多少种不同的颜色

题目分析:点数和询问都是 1 e 5 1e5 1e5 级别的,从矩阵的左侧只能等于 1 1 1 入手,将问题转换为求 x x x 的前缀和 y y y 的区间

那么自然而然想到开 50 50 50 个树状数组套线段树单独维护每个颜色,询问时单独查询即可,但这样的空间复杂度有点炸

考虑优化,因为颜色至多有 50 50 50 种,所以将颜色状压,将线段树求 “顶点个数” 的操作转换为求 “按位或” 的操作,这样只需要开一个树状数组套线段树即可,时间复杂度是 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

上面是最简单的思路,但是实现起来有一定的困难,所以考虑另一种思路

还是将每种颜色独立,每次查询我们只需要确定,是否存在着一个点 ( x x , y y ) (xx,yy) (xx,yy),满足 x x > = 1   & &   x x < = x   & &   y y > = y 1   & &   y y < = y 2 xx>=1\\ \\&\\&\\ xx<=x\\ \\&\\&\\ yy>=y1\\ \\&\\&\\ yy<=y2 xx>=1 && xx<=x && yy>=y1 && yy<=y2 即可,不难发现对于 x x x 坐标而言,有一个条件永远都满足的,所以我们不妨找出区间 [ y 1 , y 2 ] [y1,y2] [y1,y2]内的点, x x x 轴的最小值,判断其是否小于等于阈值即可,于是将题目转换为了区间求最小值,单点更新的题目了

然后就是 y y y 轴的坐标比较大,可以选择离散化或动态开点,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

代码:
动态开点:

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
	T f=1;x=0;
	char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=f;
}
template<typename T>
inline void write(T x)
{
	if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int inf=1000000;
const int N=1e6+100;
struct Node {
	int l,r,mmin;
}tree[N];
int cnt,root[51];
bool flag;
int newnode() {
	cnt++;
	tree[cnt].l=tree[cnt].r=0;
	tree[cnt].mmin=inf;
	return cnt;
}
void update(int &k,int l,int r,int pos,int val) {
	if(!k) {
		k=newnode();
	}
	tree[k].mmin=min(tree[k].mmin,val);
	if(l==r) {
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid) {
		update(tree[k].l,l,mid,pos,val);
	} else {
		update(tree[k].r,mid+1,r,pos,val);
	}
}
void query(int k,int l,int r,int ql,int qr,int val) {
	if(!k||l>qr||r<ql||flag) {
		return;
	}
	if(l>=ql&&r<=qr) {
		if(tree[k].mmin<=val) {
			flag=true;
		}
		return;
	}
	int mid=(l+r)>>1;
	query(tree[k].l,l,mid,ql,qr,val);
	query(tree[k].r,mid+1,r,ql,qr,val);

}
int cal(int x,int y1,int y2) {
	int ans=0;
	for(int i=0;i<=50;i++) {
		flag=0;
		query(root[i],1,inf,y1,y2,x);
		ans+=flag;
	}
	return ans;
}
void init() {
	cnt=-1;
	newnode();
	for(int i=0;i<=50;i++) {
		root[i]=0;
	}
}
int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	int op;
	while(scanf("%d",&op)!=EOF&&op!=3) {
		if(op==0) {
			init();
		} else if(op==1) {
			int x,y,c;
			read(x),read(y),read(c);
			update(root[c],1,inf,y,x);
		} else if(op==2) {
			int x,y1,y2;
			read(x),read(y1),read(y2);
			printf("%d\\n",cal(x,y1,y2));
		}
	}
    return 0;
}

树状数组套线段树(动态开点)

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
	T f=1;x=0;
	char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=f;
}
template<typename T>
inline void write(T x)
{
	if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
int cnt;
struct Seg {
	struct Node {
		int l,r;
		LL sum;
	}tree[150010*20*20];
	int newnode() {
		cnt++;
		tree[cnt].l=tree[cnt].r=0;
		tree[cnt].sum=0;
		return cnt;
	}
	void update(int &k,int l,int r,int pos,LL val) {
		if(!k) {
			k=newnode();
		}
		tree[k].sum|=val;
		if(l==r) {
			return;
		}
		int mid=(l+r)>>1;
		if(pos<=mid) {
			update(tree[k].l,l,mid,pos,val);
		} else {
			update(tree[k].r,mid+1,r,pos,val);
		}
	}
	LL query(int k,int l,int r,int ql,int qr) {
		if(!k||l>qr||r<ql) {
			return 0;
		}
		if(l>=ql&&r<=qr) {
			return tree[k].sum;
		}
		int mid=(l+r)>>1;
		return query(tree[k].l,l,mid,ql,qr)|query(tree[k].r,mid+1,r,ql,qr);
	}
}SEG;
struct Bit {
	int root[N];
	void add(int x,int y,LL val) {
		for(int i=x;i<N;i+=lowbit(i)) {
			SEG.update(root[i],1,1e6,y,val);
		}
	}
	LL ask(int x,int y1,int y2) {
		LL ans=0;
		for(int i=x;i>0;i-=lowbit(i)) {
			ans|=SEG.query(root[i],1,1e6,y1,y2);
		}
		return ans;
	}
}BIT;
int cal(LL x) {
	int ans=0;
	while(x) {
		ans+=x&1;
		x>>=1;
	}
	return ans;
}
void init() HDU6183 Color it  动态开点线段树

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

HDU - 6183 Color it(动态开点线段树/树状数组套动态开点线段树)

HDU 6183 Color it

HDU 6183 Color it cdq分治 + 线段树 + 状态压缩

[hdu6183][Color it]