hdu 6183 线段树的空间优化

来源:互联网 发布:遗传算法c语言代码 编辑:程序博客网 时间:2024/05/17 02:02
题意:

一个空的坐标系,有④种操作:①1 x y c表示在(x, y)点染上颜色c;②2 X y1 y2表示查询在(1, y1)到(X, y2)范围内有多少种不同的颜色:

③0表示清屏;④3表示程序退出(0<=x, y<=1000000, 0<=c<=50)


思路:开五十个线段树(一种颜色一个),以y为下表,保存min x,(因为查询x固定1---X)然后暴力查询50个就好了

但是显然碰到了一个问题,1e6 开50个线段树显然不现实。。所以需要空间优化一下。。。这里我们考虑动态来开辟线段树,有效的节点进行分配,无效则不分配。。。提问,这样空间为什么是合理的呢?其实因为一个add 最多开logn个节点,单组只有1.5e5次查询,显然,最多也就只开了qlogn个。那么这样空间复杂度就是合理的了。。具体动态开辟的实现也非常简单,类比trie,见代码。


代码:

#include<bits/stdc++.h>using namespace std;#define MEM(x,y) memset(x,y,sizeof(x));const int maxn=3e6+10;int root[55];int L[maxn],R[maxn],tot,sum[maxn];void update(int &rt,int idx,int val,int l,int r){    if(rt==-1) rt=tot++;    sum[rt]=min(val,sum[rt]);    if(l==r) return;    int mid=(l+r)/2;    if(idx<=mid) update(L[rt],idx,val,l,mid);    else update(R[rt],idx,val,mid+1,r);    return;}int query(int rt,int l,int r,int ll,int rr){    int ret=1e9;    if(rt==-1) return ret;    if(ll==l&&rr==r) return sum[rt];    int mid=(ll+rr)/2;    if(r<=mid) ret=query(L[rt],l,r,ll,mid);    else if(l>mid) ret=query(R[rt],l,r,mid+1,rr);    else ret=min(query(L[rt],l,mid,ll,mid),query(R[rt],mid+1,r,mid+1,rr));    return ret;}int main(){    int t,n,op,x,y,y1,y2,c,ret;    while(scanf("%d",&op)){        if(op==0){            MEM(L,-1);MEM(R,-1);            for(int i=0;i<maxn;++i) sum[i]=1e9;            tot=52;        }        else if(op==1){            scanf("%d%d%d",&x,&y,&c);            update(c,y,x,1,1e6);        }        else if(op==2){            scanf("%d%d%d",&x,&y1,&y2);            ret=0;            for(int i=0;i<=50;++i)                ret+=(query(i,y1,y2,1,1e6)<=x);            printf("%d\n",ret);        }        else if(op==3) break;    }}



原创粉丝点击