NOI 模擬試題(一)

                         智子入侵

【題目背景】
三體發現了人類。
在疲於應付三個無法預測規律的太陽的時候,地球是他們唯一的希望。
爲了限制住人類的基礎物理研究,避免 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章