1. 程式人生 > >2018湖南省程式設計競賽E題 動態開點線段樹

2018湖南省程式設計競賽E題 動態開點線段樹

csu還沒好,題目連線暫時沒有,省賽時沒寫出這個題,確實是線段樹水平太菜了,現在又想到了這個題,我靠水題。

思路:這個題說白了就是求最大1 到1e9這個區間有多少個點被覆蓋,普通線段樹空間肯定不行,不過可以用動態開點解決,每次更新最多新花幾十個節點的空間,1e5次更新,最多隻需幾百萬的空間足夠,解決了問題這個就是水題了。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=5e6;
int ls[maxn],rs[maxn],sum[maxn],Min[maxn],Max[maxn];
int ls2[maxn],rs2[maxn],sum2[maxn],Min2[maxn],Max2[maxn];
int n,m,cnt,cnt2;
void pushup(int o,int ls,int rs)
{
	Min[o]=min(Min[ls],Min[rs]);
	Max[o]=max(Max[ls],Max[rs]);
	sum[o]=sum[ls]+sum[rs];
}
void up(int& o,int l,int r,int ql,int qr)
{
	if(!o)o=++cnt;
	if(Min[o]==1)return;
	int mid=(l+r)/2;
	if(l>=ql&&r<=qr)
	{
		if(Max[o]==0)
		{
			Max[o]=Min[o]=1;
			sum[o]=r-l+1;
			return;
		}
		if(Min[ls[o]]==0)up(ls[o],l,mid,ql,qr);
		if(Min[rs[o]]==0)up(rs[o],mid+1,r,ql,qr);
		pushup(o,ls[o],rs[o]);
	}
	if(ql<=mid)up(ls[o],l,mid,ql,qr);
	if(qr>mid)up(rs[o],mid+1,r,ql,qr);
	pushup(o,ls[o],rs[o]);
}
void pushup2(int o,int ls,int rs)
{
	Min2[o]=min(Min2[ls],Min2[rs]);
	Max2[o]=max(Max2[ls],Max2[rs]);
	sum2[o]=sum2[ls]+sum2[rs];
}
void up2(int& o,int l,int r,int ql,int qr)
{
	if(!o)o=++cnt2;
	if(Min2[o]==1)return;
	int mid=(l+r)/2;
	if(l>=ql&&r<=qr)
	{
		if(Max2[o]==0)
		{
			Max2[o]=Min2[o]=1;
			sum2[o]=r-l+1;
			return;
		}
		if(Min2[ls2[o]]==0)up2(ls2[o],l,mid,ql,qr);
		if(Min2[rs2[o]]==0)up2(rs2[o],mid+1,r,ql,qr);
		pushup2(o,ls2[o],rs2[o]);
	}
	if(ql<=mid)up2(ls2[o],l,mid,ql,qr);
	if(qr>mid)up2(rs2[o],mid+1,r,ql,qr);
	pushup2(o,ls2[o],rs2[o]);
}
int main()
{
	int op,a,b,q;
	while(~scanf("%d%d%d",&n,&m,&q))
	{
		cnt=cnt2=0;
		int rt=0,rt2=0;
		while(q--)
		{
			scanf("%d%d%d",&op,&a,&b);
			if(op==1)
			up(rt,1,n,a,b);
			else up2(rt2,1,m,a,b);
			ll ans=1ll*sum[1]*m;
			ans+=1ll*sum2[1]*n;
			ans-=1ll*sum[1]*sum2[1];
			ans=1ll*n*m-ans+1;
			if(sum[1]==0)
			ans=1ll*(m-sum2[1])*n+sum2[1];
			if(sum2[1]==0)
			ans=1ll*(n-sum[1])*n+sum[1];
			printf("%lld\n",ans); 
		}
		for(int i=1;i<=cnt;i++)
		sum[i]=Min[i]=Max[i]=0;
		for(int i=1;i<=cnt2;i++)
		sum2[i]=Min2[i]=Max2[i]=0;
	}
}