C. Rooks Defenders Codeforces Round #791 (Div. 2)(树状数组!)

传送门

题意:给你一个n*n的棋盘,然后给你一个t(t只能为1,2,3),对于不同的t产生不同的影响:

t=1时,给你一个点的坐标x,y,在这个点上生成一辆坦克(保证在这之前没有坦克)

t=2时,给你一个点的坐标x,y,把这个点上的坦克移除(保证在这之前这个点有坦克)

t=3时,给你两个点的坐标x1,y1,x2,y2,让你求两个点生成的矩阵的所有点能不能保证有一辆坦克能攻击到他,如果可以输出“Yes”,否则输出“No”。

注:每个坦克可以攻击的范围是他的一行和一列的所有格子。

思路:因为要求范围内的值,然后就是 前缀和处理,但是因为时间复杂度是1e5,所以得用树状数组减少复杂度,先创建两个,一个用来计算x(行)的前n项的和,代表有多少坦克,一个是计算y(列)的前n项和,然后这样可以计算某个范围内有多少辆坦克,但是因为我们要求的是范围内的所有的点都能被坦克攻击,那么就要保证要么每一行都有一个坦克要么每一列都有一辆坦克 ,但是我们目前的数组还求不出,(可能某一行有多个坦克)

那么我们可以再创建两个数组stx和sty,当t为1 的时候并且当前x(y)的坦克数量为1 的时候就在stx数组上加一个1表示这个地方有坦克,(t等于2同理坦克数量为0 的时候st--代表没有坦克)。

然后t等于3因为st数组存的是当前行(列)有没有坦克,那么可以用st数组来计算满不满足当前条件。

代码:

/**
*  ┏┓   ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃       ┃
* ┃   ━   ┃ ++ + + +
*  ████━████+
*  ◥██◤ ◥██◤ +
* ┃   ┻   ┃
* ┃       ┃ + +
* ┗━┓   ┏━┛
*   ┃   ┃ + + + +Code is far away from  
*   ┃   ┃ + bug with the animal protecting
*   ┃    ┗━━━┓ 神兽保佑,代码无bug 
*   ┃  	    ┣┓
*    ┃        ┏┛
*     ┗┓┓┏━┳┓┏┛ + + + +
*    ┃┫┫ ┃┫┫
*    ┗┻┛ ┗┻┛+ + + +
*/

#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long 
using namespace std;

const int N=100000+100;
int n ,m,h;
int xx[N],yy[N];
int stx[N],sty[N];

int lowbit(int x){return x&(-x);}

void add(int x,int sum,int a[])
{
	for(int i =x;i<=n;i+=lowbit(i))
	a[i]+=sum;
}	

int get(int x,int a[])
{
	int res=0;
	for(int i =x;i;i-=lowbit(i))
	{
		res+=a[i];
	}
	return res;
}


int main()
{
	int t;
	cin>>n>>m;
	while(m--)
	{
		int t,x,y,x1,x2,y1,y2 ;
		sc_int(t);
		if(t==1)
		{
			sc_int(x),sc_int(y);
			add(x,1,xx),add(y,1,yy);
			if(get(x,xx)-get(x-1,xx)==1)
			add(x,1,stx);
			if(get(y,yy)-get(y-1,yy)==1)
			add(y,1,sty);			
		}
		else if(t==2)
		{
			sc_int(x),sc_int(y);
			add(x,-1,xx),add(y,-1,yy);
			if(get(x,xx)-get(x-1,xx)==0)
			add(x,-1,stx);
			if(get(y,yy)-get(y-1,yy)==0)
			add(y,-1,sty);				
		}
		else {
			sc_int(x1),sc_int(y1);
			sc_int(x2),sc_int(y2);			
			if(get(x2,stx)-get(x1-1,stx)==x2-x1+1||get(y2,sty)-get(y1-1,sty)==y2-y1+1)
			printf("YES\n");
			else printf("No\n");
		}
	}
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值