2018.10.23【校內模擬】行星通道計劃(二維樹狀陣列)(樹套樹)
阿新 • • 發佈:2018-12-17
傳送門
解析:
我們發現,每一條線段會把原來的環狀分成兩段,兩條線段有交點當且僅當一條線段的起終點分別在另一條線段把環形分成的兩個部分中。
所以直接斷環成鏈,每次新加線段就等同於詢問起點在之間且終點在之間的線段數,加上起點在之間,終點在之間的線段個數。這就是它相交的線段數。
容易想到用一種資料結構來維護起點在之間的線段的終點的位置。那麼就是顯然的樹套樹。
但是這個樹套樹可以用二維樹狀陣列來代替,然而蒟蒻考場上沒想出來打了一個線段樹套被卡常數了。
下來後直接把改成樹狀陣列就了。。。
這就是不注意常數的下場。。。
程式碼:
#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;
}