列表

详情


NC54307. 银老板的游戏

描述

银灰,你的盟友,前来助力。你不会让我失望的,对吗。

众所周知,银老板喜欢爬猫爬架,还喜欢和博士下棋。

这一天,银灰又来到宿舍找Dr.
消磨时间尚有更好的方法。想不想尝试一下?
然后,你掏出了棋盘,结果银老板制止了你,你娇羞(划掉)不解的看向银灰,银灰从背后取出一张硕大的网格图
随即,银老板向你介绍了游戏规则
银灰会用他的拐杖在棋盘上画若干个矩形,当然,也有可能擦除之前画的某个矩形
同时,银灰会向你抛出若干个问题,你需要正确回答他的问题,否则你将会失去来自喀兰之主的一份大礼
由于银灰的问题实在来的太快太难了,你需要设计一个程序解决他的问题

输入描述

第一行1个整数,Q,表示操作的数量

接下来Q行

若输入为1 a b x y,表示银老板用拐杖画了一个左下角坐标为(a,b),右上角坐标为(x,y)的矩形(保证合法)

若输入为2 x,表示银老板擦除了他在第x次操作中画下的矩形(请注意,即使这个矩形被擦除,在后面的操作中仍然具有影响,具体请看样例)

若输入为3 a b x y,表示银老板抛出了一个询问,他想知道当前网格图上有多少矩形和一个左下角为(a,b),右上角为(x,y)的矩形有交点(四个顶点也算,只有边重合也算)

输出描述

若干行,对于每个询问,请输出对应的答案

示例1

输入:

5
1 1 1 2 2
1 2 2 3 3
3 3 3 4 4 
2 2
3 3 3 4 4

输出:

1
0

说明:

对于第一次询问,第二个矩形(2,2)->(3,3)与其有交点,但是当擦除第二个矩形后,就没有矩形和它有交点了,故第二次询问输出0

示例2

输入:

9
1 1 2 3 4
1 2 2 3 3
1 4 4 8 8
3 3 3 4 4
3 5 3 6 8
2 2
3 2 1 6 8
2 3
3 3 1 4 5

输出:

3
1
2
1

说明:

第一次询问,如图(虚线部分为询问的矩形)
第二次询问,如图
第一次删除,操作后如图,
第三次询问,如图
第二次删除操作,操作后如图
第四次询问,如图

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 1054ms, 内存消耗: 9188K, 提交时间: 2019-11-23 09:53:43

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define low(x) (x&-(x))
using namespace std;

struct type{
	int x1,y1,x2,y2,s,id;
} a[100001],b[100001];
struct Type{
	int s,id;
} c[200001];
struct type1{
	int x,s,id;
} d[100001];
struct type2{
	int x,y,s,id,Id;
} D[100001];
int tr[200001];
int ans[200001];
int n,i,j,k,l,tp,tot,Tot,sum,len;

bool Cmp(Type a,Type b) {return a.s<b.s;}
bool cmp(type2 a,type2 b) {return a.x<b.x || a.x==b.x && a.id>b.id;}

void change(int t,int s)
{
	while (t<=200000)
	{
		tr[t]+=s;
		t+=low(t);
	}
}

void clear(int t)
{
	while (t<=200000)
	{
		tr[t]=0;
		t+=low(t);
	}
}

int find(int t)
{
	int ans=0;
	
	while (t)
	{
		ans+=tr[t];
		t-=low(t);
	}
	
	return ans;
}

void work1()
{
	int i;
	
	fo(i,1,n)
	if (d[i].s)
	change(d[i].x,d[i].s);
	else
	ans[d[i].id]-=find(d[i].x-1);
	
	memset(tr,0,sizeof(tr));
}

void work2(int l,int r)
{
	int i,mid=(l+r)/2;
	
	if (l==r) return;
	
	work2(l,mid);
	work2(mid+1,r);
	
	sort(D+l,D+r+1,cmp);
	
	fo(i,l,r)
	if (D[i].Id<=mid && D[i].s)
	change(D[i].y,D[i].s);
	else
	if (D[i].Id>mid && !D[i].s)
	ans[D[i].id]+=find(D[i].y-1);
	
	fo(i,l,r)
	if (D[i].Id<=mid && D[i].s)
	clear(D[i].y);
}

int main()
{
//	freopen("e.in","r",stdin);
	
	scanf("%d",&n);
	fo(i,1,n)
	{
		scanf("%d",&tp);
		
		switch (tp)
		{
			case 1:{
				scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
				
				++sum;
				a[i].s=1;
				b[++tot]=a[i];
				break;
			}
			case 2:{
				scanf("%d",&j);
				
				--sum;
				a[i]=b[j];
				a[i].s=-1;
				break;
			}
			case 3:{
				scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
				
				a[i].id=++Tot;
				ans[Tot]=sum;
				break;
			}
		}
	}
	
//	---
	
	len=0;
	fo(i,1,n)
	{
		c[++len]={a[i].x1,i};
		c[++len]={a[i].x2,-i};
	}
	sort(c+1,c+len+1,Cmp);
	j=0;
	fo(i,1,len)
	{
		j+=i==1 || c[i].s!=c[i-1].s;
		
		if (c[i].id>0)
		a[c[i].id].x1=j;
		else
		a[-c[i].id].x2=j;
	}
	
	len=0;
	fo(i,1,n)
	{
		c[++len]={a[i].y1,i};
		c[++len]={a[i].y2,-i};
	}
	sort(c+1,c+len+1,Cmp);
	j=0;
	fo(i,1,len)
	{
		j+=i==1 || c[i].s!=c[i-1].s;
		
		if (c[i].id>0)
		a[c[i].id].y1=j;
		else
		a[-c[i].id].y2=j;
	}
	
//	---
	
	fo(i,1,n)
	if (a[i].s)
	d[i]={a[i].x2,a[i].s,0};
	else
	d[i]={a[i].x1,0,a[i].id};
	work1();
	
	fo(i,1,n)
	if (a[i].s)
	d[i]={200001-a[i].x1,a[i].s,0};
	else
	d[i]={200001-a[i].x2,0,a[i].id};
	work1();
	
	fo(i,1,n)
	if (a[i].s)
	d[i]={a[i].y2,a[i].s,0};
	else
	d[i]={a[i].y1,0,a[i].id};
	work1();
	
	fo(i,1,n)
	if (a[i].s)
	d[i]={200001-a[i].y1,a[i].s,0};
	else
	d[i]={200001-a[i].y2,0,a[i].id};
	work1();
	
//	---
	
	fo(i,1,n)
	if (a[i].s)
	D[i]={a[i].x2,a[i].y2,a[i].s,0};
	else
	D[i]={a[i].x1,a[i].y1,0,a[i].id};
	fo(i,1,n)
	D[i].Id=i;
	work2(1,n);
	
	fo(i,1,n)
	if (a[i].s)
	D[i]={200001-a[i].x1,200001-a[i].y1,a[i].s,0};
	else
	D[i]={200001-a[i].x2,200001-a[i].y2,0,a[i].id};
	fo(i,1,n)
	D[i].Id=i;
	work2(1,n);
	
	fo(i,1,n)
	if (a[i].s)
	D[i]={a[i].x2,200001-a[i].y1,a[i].s,0};
	else
	D[i]={a[i].x1,200001-a[i].y2,0,a[i].id};
	fo(i,1,n)
	D[i].Id=i;
	work2(1,n);
	
	fo(i,1,n)
	if (a[i].s)
	D[i]={200001-a[i].x1,a[i].y2,a[i].s,0};
	else
	D[i]={200001-a[i].x2,a[i].y1,0,a[i].id};
	fo(i,1,n)
	D[i].Id=i;
	work2(1,n);
	
//	---
	
	fo(i,1,Tot)
	printf("%d\n",ans[i]);
}

C++14(g++5.4) 解法, 执行用时: 472ms, 内存消耗: 9988K, 提交时间: 2020-01-07 14:36:53

#include<bits/stdc++.h>
#define N 200010
#define lb lower_bound
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
using namespace std;
int lx[N],ly[N],ans[N],op[N],nx,ny,n;
struct rd{
    int a,b,c,op;
}w[N],tmp[N];
struct rec{
    int a,b,x,y;
    void read(){scc(a,b);scc(x,y);lx[++nx]=a,lx[++nx]=x,ly[++ny]=b,ly[++ny]=y;}
}G[N],T[N];

struct bit{
    int d[N];
    void up(int x,int y){for(;x<N;x+=x&-x) d[x]+=y; }
    inline int get(int x){int r=0; for(;x;x-=x&-x) r+=d[x]; return r; }
    void cls(){memset(d,0,sizeof d); }
}U,D,L,R;

void CDQ(int l,int r){
    if (l==r) return;
    int t=l+r>>1,x=l,y=t+1,k=l;
    CDQ(l,t);
    CDQ(t+1,r);
    while(x<=t && y<=r){
        if (w[x].b<=w[y].b){
            U.up(w[x].c,w[x].op);
            tmp[k++]=w[x++];
        } else {
            ans[w[y].a]+=U.get(w[y].c);
            tmp[k++]=w[y++];
        }
    }
    while(y<=r){
        ans[w[y].a]+=U.get(w[y].c);
        tmp[k++]=w[y++];
    }
    for (int i=l;i<x;i++) U.up(w[i].c,-w[i].op);
    while(x<=t) tmp[k++]=w[x++];
    for (int i=l;i<=r;i++) w[i]=tmp[i];
}

void solve(int f1,int f2){
    for(int i=1;i<=n;i++)
        if (op[i]!=3) w[i]=rd{i,f1?N-G[i].a:G[i].x,f2?N-G[i].b:G[i].y,op[i]==1?1:-1}; else
                      w[i]=rd{i,f1?N-G[i].x-1:G[i].a-1,f2?N-G[i].y-1:G[i].b-1,0};
    CDQ(1,n);
}

int main(){
    sc(n); int tt=0;
    for(int num=0,x,i=1;i<=n;i++){
        sc(op[i]);
        if (op[i]==1) num++;else
        if (op[i]==2) num--;else
        if (op[i]==3) ans[i]=num;
        if (op[i]!=2) G[i].read();
        else{
            sc(x);
            G[i]=T[x];
        }
        if (op[i]==1) T[++tt]=G[i];
    }

    sort(lx+1,lx+nx+1); sort(ly+1,ly+ny+1);
    nx=unique(lx+1,lx+nx+1)-lx-1, ny=unique(ly+1,ly+ny+1)-ly-1;
    for(int i=1;i<=n;i++)
        G[i].a=lb(lx+1,lx+nx+1,G[i].a)-lx+1,
        G[i].x=lb(lx+1,lx+nx+1,G[i].x)-lx+1,
        G[i].b=lb(ly+1,ly+ny+1,G[i].b)-ly+1,
        G[i].y=lb(ly+1,ly+ny+1,G[i].y)-ly+1;

    for(int i=1;i<=n;i++){
        int tg;
        if (op[i]==1) tg=1;else
        if (op[i]==2) tg=-1;
        if (op[i]!=3){
            L.up(G[i].x,tg);
            R.up(N-G[i].a,tg);
            U.up(N-G[i].b,tg);
            D.up(G[i].y,tg);
        }else{
            ans[i]-=L.get(G[i].a-1);
            ans[i]-=R.get(N-G[i].x-1);
            ans[i]-=U.get(N-G[i].y-1);
            ans[i]-=D.get(G[i].b-1);
        }
    }

    U.cls();
    solve(0,0);     // L D
    solve(0,1);     // L U
    solve(1,0);     // R D
    solve(1,1);     // R U
    for(int i=1;i<=n;i++) if (op[i]==3) printf("%d\n",ans[i]);
}

上一题