bzoj4066(kd_tree 维护权值)

 

话说本来想写替罪羊重构,可是后来发现狂T不止。

 

其实还有一个思路是,动态维护kdtree,每次插入log 个节点,坐标完全是实际坐标,需要n log n的空间,本题卡空间

 

/**************************************************************
    Problem: 4066
    User: zhhx
    Language: C++
    Result: Accepted
    Time:49076 ms
    Memory:12468 kb
****************************************************************/
 
#include<cstdio>    
#include<cmath>    
#include<cstdlib>    
#include<algorithm>    
#include<cstring>    
#include<stack>    
using namespace std;    
         
inline int read()    
{    
    int ans,f=1;char ch;    
    while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';    
    while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';    
    return ans*f;    
}    
         
         
int D;    
         
int n,m,ans,val;    
int num;    
struct aaa    
{    
    int d[2],val;    
}tmp[200005];    
struct aa    
{    
    int mi[2],mx[2],d[2];    
    int sum,size,val;    
    int lc,rc;    
}a[200005];    
void up(int u,int v)    
{    
    for (int i=0;i<=1;i++)    
    {    
        a[u].mi[i]=min(a[u].mi[i],a[v].mi[i]);    
        a[u].mx[i]=max(a[u].mx[i],a[v].mx[i]);    
    }    
    a[u].size=a[a[u].lc].size+a[a[u].rc].size+1;    
    a[u].sum=a[a[u].lc].sum+a[a[u].rc].sum+a[u].val;    
}    
stack<int> s;    
int uu,fa,rt;    
int new_node()    
{    
    int u;    
    if (s.empty()) return u=++n;    
    else u=s.top(),s.pop();    
    return u;    
}    
void insert(int &u,int d[2],int dd)    
{    
    if (u==0)     
    {    
        u=new_node();    
        a[u].mi[0]=a[u].mx[0]=a[u].d[0]=d[0];    
        a[u].mi[1]=a[u].mx[1]=a[u].d[1]=d[1];    
        a[u].sum=a[u].val=val;a[u].size=1;a[u].lc=a[u].rc=0;    
        return;     
    }    
    if (a[u].d[0]==d[0]&&a[u].d[1]==d[1])    
    {    
        a[u].sum+=val,a[u].val+=val;    
        return ;    
    }    
    if (a[u].d[dd]>d[dd]) {insert(a[u].lc,d,dd^1),up(u,a[u].lc);if (a[u].lc==uu) fa=u;}    
    else {insert(a[u].rc,d,dd^1),up(u,a[u].rc);if (a[u].rc==uu) fa=u;}    
             
    int mx=max(a[a[u].lc].size,a[a[u].rc].size); 
    if (mx>0.63*a[u].size&&a[u].size>10000) uu=u;  
}    
     
     
bool in(int x,int y,int xx,int yy,int d1[2],int d2[2])  
{  
    if (d1[0]<=x&&d1[1]<=y&&d2[0]>=xx&&d2[1]>=yy) return true;return false;  
}  
bool out(int x,int y,int xx,int yy,int d1[2],int d2[2])  
{  
    if (d2[0]<x||d2[1]<y||d1[0]>xx||d1[1]>yy) return true;return false;  
}  
     
int query(int u,int d1[2],int d2[2])    
{    
    if (u==0) return 0;    
    if (out(a[u].mi[0],a[u].mi[1],a[u].mx[0],a[u].mx[1],d1,d2)) return 0;  
    if (in(a[u].mi[0],a[u].mi[1],a[u].mx[0],a[u].mx[1],d1,d2)) return a[u].sum;    
    int ans=0;  
    if (in(a[u].d[0],a[u].d[1],a[u].d[0],a[u].d[1],d1,d2)) ans+=a[u].val;//注意当前节点本身的值,这里wa了好几次  
    ans+=query(a[u].lc,d1,d2)+query(a[u].rc,d1,d2);  
    return ans;  
}    
void dfs(int u)    
{    
    if (u==0) return ; 
    s.push(u);    
    num++;    
    tmp[num].d[0]=a[u].d[0];    
    tmp[num].d[1]=a[u].d[1];    
    tmp[num].val=a[u].val;    
    dfs(a[u].lc);dfs(a[u].rc);    
}    
bool cmp(aaa a,aaa b)    
{    
    return  a.d[D]<b.d[D]||(a.d[0]==b.d[0]&&a.d[1]<b.d[1]);    
}    
int build(int l,int r,int dd)    
{    
    int mid=(l+r)>>1;    
    D=dd;    
    nth_element(tmp+l,tmp+mid,tmp+r+1,cmp);    
             
    int u=new_node();   
    a[u].mi[0]=a[u].mx[0]=a[u].d[0]=tmp[mid].d[0];    
    a[u].mi[1]=a[u].mx[1]=a[u].d[1]=tmp[mid].d[1];    
    a[u].size=1;a[u].val=a[u].sum=tmp[mid].val;    
    if (l<mid) a[u].lc=build(l,mid-1,dd^1),up(u,a[u].lc);else a[u].lc=0;    
    if (mid<r) a[u].rc=build(mid+1,r,dd^1),up(u,a[u].rc);else a[u].rc=0;    
    return u;  
}    
         
void rebuild(int u)    
{ 
    num=0;    
    dfs(u);   
       
    int tt=build(1,num,0); 
    if (fa==0) {rt=tt;return;}    
    if (a[fa].lc==u) a[fa].lc=tt;    
    else a[fa].rc=tt;    
} 
int main()    
{    
    int nn=read(); 
    int op,d1[2],d2[2];    
    while (true)    
    {    
        op=read();    
        if (op==3) break;    
        if (op==1)     
        {    
            d1[0]=read()^ans,d1[1]=read()^ans,val=read()^ans;    
                     
            fa=uu=0;    
            insert(rt,d1,0);    
            if (rt==uu) fa=0;   
            if (uu>0) rebuild(uu);   
        }    
        else
        {    
            d1[0]=read()^ans,d1[1]=read()^ans,d2[0]=read()^ans,d2[1]=read()^ans;    
            ans=query(rt,d1,d2);  
            printf("%d\n",ans);  
        }  
    }  
    return 0;    
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值