bzoj白花蛇草水 树套树
bzoj4605: 崂山白花蛇草水
思路
强制在线,那就权值线段树套KDtree好了,没啥好讲的。
权值线段树上二分就可以了。
权值线段树要动态开点
KDtree要加平衡因子来重构。另外,那水真难喝。
错误
树套树一边写过了,然后是各种傻***错误。
我居然离散化了权值,要被gzy嘲笑了。
我一开始还笑话那些写动态开点的慢,
然后就被啪啪脸了。
我回收内存不知道咋的多了个if。
然后就逼近内存上限半个G。
总之就是很多傻吊错误。
代码
#include #define cmin(a,b) (a>b?a=b:a) #define cmax(a,b) (a>b?a:a=b) using namespace std; const int N=1e5+7; const double alpha=0.8; int read() { int x=0,f=1;char s=getchar(); for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1; for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0'; return x*f; } int Wn; struct point {int x[2];} p[N]; bool cmp(point a,point b) { return a.x[Wn]<b.x[Wn]; } struct kdnode { int ch[2],ma[2],mi[2],siz; point a; }t[N*30]; int stak[N*30],top,num; int newnode() { if(top) return stak[top--]; return ++num; } void update(int x,int y) { cmin(t[x].mi[0],t[y].mi[0]); cmin(t[x].mi[1],t[y].mi[1]); cmax(t[x].ma[0],t[y].ma[0]); cmax(t[x].ma[1],t[y].ma[1]); } void up(int u) { t[u].siz=t[t[u].ch[0]].siz+t[t[u].ch[1]].siz+1; t[u].mi[0]=t[u].ma[0]=t[u].a.x[0]; t[u].mi[1]=t[u].ma[1]=t[u].a.x[1]; if(t[u].ch[0]) update(u,t[u].ch[0]); if(t[u].ch[1]) update(u,t[u].ch[1]); } int build(int l,int r,int wn) { if(l>r) return 0; int mid=(l+r)>>1; Wn=wn; nth_element(p+l,p+mid,p+r+1,cmp); int u=newnode(); t[u].a=p[mid]; t[u].ch[0]=build(l,mid-1,wn^1); t[u].ch[1]=build(mid+1,r,wn^1); up(u); return u; } void pia(int u,int num) { if(t[u].ch[0]) pia(t[u].ch[0],num); p[num+t[t[u].ch[0]].siz+1]=t[u].a; stak[++top]=u; if(t[u].ch[1]) pia(t[u].ch[1],num+t[t[u].ch[0]].siz+1); } void check(int &x,int wn) { if(t[x].siz*alpha<t[t[x].ch[0]].siz||t[x].siz*alpha<t[t[x].ch[1]].siz) pia(x,0),x=build(1,t[x].siz,wn); } void insert(point a,int &u,int wn) { if(!u) { u=newnode(); t[u].a=a; t[u].ch[0]=t[u].ch[1]=0; up(u); return; } if(a.x[wn]<t[u].a.x[wn]) insert(a,t[u].ch[0],wn^1); else insert(a,t[u].ch[1],wn^1); up(u),check(u,wn); } int pd(point a,point b,int k) { if(a.x[0]<=t[k].mi[0]&&t[k].ma[0]<=b.x[0]&& a.x[1]<=t[k].mi[1]&&t[k].ma[1]<=b.x[1]) return 2; if(a.x[0]>t[k].ma[0]||b.x[0]<t[k].mi[0]) return 0; if(a.x[1]>t[k].ma[1]||b.x[1]<t[k].mi[1]) return 0; return 1; } int query(point a,point b,int u) { if(!u||!pd(a,b,u)) return 0; if(pd(a,b,u)==2) return t[u].siz; int ans=0; if(a.x[0]<=t[u].a.x[0]&&t[u].a.x[0]<=b.x[0]&&a.x[1]<=t[u].a.x[1]&&t[u].a.x[1]<=b.x[1]) ans++; ans+=query(a,b,t[u].ch[0]); ans+=query(a,b,t[u].ch[1]); return ans; } namespace seg { struct dsr_sb { int ch[2],rt; }t[N*30]; int tot; void insert(int l,int r,int &u,point a,int val) { if(!u) u=++tot; insert(a,t[u].rt,0); if(l==r) return; int mid=(l+r)>>1; if(val<=mid) insert(l,mid,t[u].ch[0],a,val); else insert(mid+1,r,t[u].ch[1],a,val); } int ask(int l,int r,int u,point a,point b,int k) { if(l==r) return l; int mid=(l+r)>>1,tmp=query(a,b,t[t[u].ch[1]].rt); if(k>tmp) return ask(l,mid,t[u].ch[0],a,b,k-tmp); else return ask(mid+1,r,t[u].ch[1],a,b,k); } } int main() { int n=read(),q=read(),lastans=0,rt=0; n+=n; for(int i=1;i<=q;++i) { int opt=read(),k; point a,b; a.x[0]=read()^lastans,a.x[1]=read()^lastans; if(opt==1) { k=read()^lastans; seg::insert(1,1e9,rt,a,k); } else { b.x[0]=read()^lastans,b.x[1]=read()^lastans; k=read()^lastans; int tmp=query(a,b,seg::t[rt].rt); if(k>tmp) { puts("NAIVE!ORZzyz."); lastans=0; } else { lastans=seg::ask(1,1e9,rt,a,b,k); printf("%d\n",lastans); } } } return 0; }