智子入侵
【題目背景】
三體發現了人類。
在疲於應付三個無法預測規律的太陽的時候,地球是他們唯一的希望。
爲了限制住人類的基礎物理研究,避免 300 年的技術爆炸,智子到達了地球。
目標:所有的粒子對撞機。
【題目描述】
作爲三體人的科學執政官,元首需要你想他彙報智子每一次攻擊的成果。軍事執政官
已經把智子的攻擊計劃提交給你,而人類的一舉一動也在智子的監視之下。你需要計算出
每一次智子的攻擊能夠摧毀多少個對撞機。
把地球的地面抽象爲一個網格平面,對撞機佔據一塊邊界與座標軸平行的矩形地面,
而智子每次只攻擊一個格子。一個對撞機的任意一部分被攻擊到,則整個對撞機被徹底摧
毀。
需要注意的是,對撞機之間可以重疊。
【輸入】(collider.in)
文件的第一行有一個正整數 n,表示你所知道的 n 個事件。接下來的 n 行描述 n 個事
件(它們按輸入的順序依次發生)。事件只有兩種:Build & Destroy(B & D)。
第 i+1 行(i>=1)描述了第 i 個事件,每一行的開頭是一個字母,表示事件的種類,格
式如下:
B x1 y1 x2 y3:建造一個對撞機,左下角座標爲(x1,y1),右上角座標爲(x2,y2)
D x1 y1:智子進行了一次攻擊,座標爲(x1,y1)
注意,座標均爲正整數。B 和 D 爲大寫。
【輸出】(collider.out)
對於每一次智子的攻擊,在單獨的一行裏輸出這一次攻擊摧毀掉的對撞機個數。
【樣例輸入】
4
B 1 1 3 3
B 3 3 5 5
D 3 3
D 3 3
【樣例輸出】
2
0
【數據規模】
25%的數據 n<=1000 x,y<=500
50%的數據 n<=10000 x,y<=500
100%的數據 n<=200000 x,y<=1500
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=200010,M=1510,K=25000010;
struct Data
{
int tp,x1,y1,x2,y2;
} q[N];
int cnt,rt[M<<2],ch[K][2],Min[K];
int Q,ans[N];
char tp[10];
#define mid ((l+r)>>1)
int NewNode()
{
Min[++cnt]=K;
return cnt;
}
void Inserty(int &x,int l,int r,int gy,int key)
{
if(!x)x=NewNode();
if(l==r)
{
Min[x]=min(Min[x],key);
return;
}
if(mid>=gy)Inserty(ch[x][0],l,mid,gy,key);
else Inserty(ch[x][1],mid+1,r,gy,key);
Min[x]=min(Min[ch[x][0]],Min[ch[x][1]]);
}
void Insertx(int x,int l,int r,int gx,int gy,int key)
{
Inserty(rt[x],1,1500,gy,key);
if(l==r)return;
if(mid>=gx)Insertx(x<<1,l,mid,gx,gy,key);
else Insertx(x<<1|1,mid+1,r,gx,gy,key);
}
int Queryy(int x,int l,int r,int y1,int y2)
{
if(!x)return K;
if(l>=y1&&r<=y2)return Min[x];
int ret=K;
if(mid>=y1)ret=min(ret,Queryy(ch[x][0],l,mid,y1,y2));
if(mid<y2)ret=min(ret,Queryy(ch[x][1],mid+1,r,y1,y2));
return ret;
}
int Queryx(int x,int l,int r,int x1,int x2,int y1,int y2)
{
if(l>=x1&&r<=x2)return Queryy(rt[x],1,1500,y1,y2);
int ret=K;
if(mid>=x1)ret=min(ret,Queryx(x<<1,l,mid,x1,x2,y1,y2));
if(mid<x2)ret=min(ret,Queryx(x<<1|1,mid+1,r,x1,x2,y1,y2));
return ret;
}
int main()
{
freopen("collider.in","r",stdin);
freopen("collider.out","w",stdout);
scanf("%d",&Q);
Min[0]=K;
for(int i=1; i<=Q; i++)
{
scanf("%s",tp);
if(tp[0]=='B')
{
q[i].tp=1;
scanf("%d%d",&q[i].x1,&q[i].y1);
scanf("%d%d",&q[i].x2,&q[i].y2);
}
if(tp[0]=='D')
{
q[i].tp=2;
scanf("%d%d",&q[i].x1,&q[i].y1);
}
}
for(int i=Q; i>=1; i--)
{
if(q[i].tp==2)
Insertx(1,1,1500,q[i].x1,q[i].y1,i);
else
{
int ret=Queryx(1,1,1500,q[i].x1,q[i].x2,q[i].y1,q[i].y2);
if(ret!=K)ans[ret]+=1;
}
}
for(int i=1; i<=Q; i++)
if(q[i].tp==2)
printf("%d\n",ans[i]);
return 0;
}