1. 程式人生 > >2018.10.23【校內模擬】行星通道計劃(二維樹狀陣列)(樹套樹)

2018.10.23【校內模擬】行星通道計劃(二維樹狀陣列)(樹套樹)

傳送門

解析:

我們發現,每一條線段會把原來的環狀分成兩段,兩條線段有交點當且僅當一條線段的起終點分別在另一條線段把環形分成的兩個部分中。

所以直接斷環成鏈,每次新加線段<u,v><u,v>就等同於詢問起點在1,u1,u之間且終點在u,vu,v之間的線段數,加上起點在u,vu,v之間,終點在v,nv,n之間的線段個數。這就是它相交的線段數。

容易想到用一種資料結構來維護起點在l,rl,r之間的線段的終點的位置。那麼就是顯然的樹套樹。

但是這個樹套樹可以用二維樹狀陣列來代替,然而蒟蒻考場上沒想出來打了一個線段樹套T

reapTreap被卡常數了。

下來後直接把TreapTreap改成樹狀陣列就AA了。。。

這就是不注意常數的下場。。。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=
c^48; while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return num; } inline void outint(ll a){ static char ch[23]; if(a==0)pc('0'); while(a)ch[++ch[0]]=a-a/10*10,a/=10; while(ch[0])pc(ch[ch[0]--]^48); } cs int N=1003; #define lowbit(x) (x&(-x)) struct treearray{ int a[N]; inline void
Insert(int k){ for(;k<N;k+=lowbit(k))++a[k]; } inline int queryrank(int pos){ re int res=0; for(;pos;pos-=lowbit(pos))res+=a[pos]; return res; } inline void Delete(int k){ for(;k<N;k+=lowbit(k))--a[k]; } }Tree[N<<2]; inline int query(cs int &k,cs int &l,cs int &r,cs int &ql,cs int &qmd,cs int &qr){//begin from ql to qmd ,end point in qmd to qr if(ql<=l&&r<=qmd){ return Tree[k].queryrank(qr)-Tree[k].queryrank(qmd-1); } int mid=(l+r)>>1; if(qmd<=mid)return query(k<<1,l,mid,ql,qmd,qr); if(ql>mid)return query(k<<1|1,mid+1,r,ql,qmd,qr); return query(k<<1,l,mid,ql,qmd,qr)+query(k<<1|1,mid+1,r,ql,qmd,qr); } inline void update(cs int &k,cs int &l,cs int &r,cs int &be,cs int &en){ Tree[k].Insert(en); if(l==r)return ; int mid=(l+r)>>1; if(mid<be)update(k<<1|1,mid+1,r,be,en); else update(k<<1,l,mid,be,en); } inline void erase(cs int &k,cs int &l,cs int &r,cs int &be,cs int &en){ Tree[k].Delete(en); if(l==r)return ; int mid=(l+r)>>1; if(mid<be)erase(k<<1|1,mid+1,r,be,en); else erase(k<<1,l,mid,be,en); } cs int M=500005; int from[M],to[M]; int n,m; signed main(){ srand(time(0)); n=getint(); m=getint(); for(int re i=1;i<=m;++i){ int op=getint(); int x=getint(),y; switch(op){ case 0:{ y=getint(); if(x>y)swap(x,y); from[i]=x,to[i]=y; int ans=query(1,1,n,1,x,y); ans+=query(1,1,n,x,y,n); outint(ans);pc('\n'); update(1,1,n,x,y); break; } case 1:{ if(from[x]&&to[x])erase(1,1,n,from[x],to[x]); from[x]=to[x]=0; break; } } } return 0; }