题目描述

Consider a square map with N × N cells. We indicate the coordinate of a cell by (i, j), where 1 ≤ i, j ≤ N . Each cell has a color either white or black. The color of each cell is initialized to white. The map supports the operation
flip([xlow , xhigh], [ylow , yhigh]), which flips the color of each cell in the rectangle [xlow , xhigh] × [ylow , yhigh]. Given
a sequence of flip operations, our problem is to count the number of black cells in the final map. We illustrate this in the following example. Figure (a) shows the initial map. Next, we call flip([2, 4], [1, 3]) and obtain Figure (b). Then, we call flip([1, 5], [3, 5]) and obtain Figure (c). This map contains 18 black cells.

输入

The first line contains the number of test cases T (T < 10). Each test case begins with a line containing two integers N and K (1 < N, K < 10000), where N is the parameter of the map size and K is the number of flip operations. Each subsequent line corresponds to a flip operation, with four integers: xlow , xhigh, ylow , yhigh.

输出

For each test case, output the answer in a line.

样例输入

1
5 2
2 4 1 3
1 5 3 5

样例输出

18

题意:给你一个n*n的白色方块,然后有m次修改,其中每次询问修改一个矩形,这个矩形中的黑块变白,白快变黑,问最后有多少个黑块
思路:扫描线算法+线段树维护
代码如下:
#include <bits/stdc++.h>
using namespace std;
int read() {
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
} while('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
} return x * f;
}
const int maxn = 1e5+500;
int n,m,tot=0;
int sum[maxn<<2],cnt[maxn<<2],tag[maxn<<2];
struct node
{
int x,y1,y2;
bool operator < (const node &p) const{return x<p.x;}
}qu[maxn<<1];
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];//求当前行(线段树)中黑色的块数
cnt[rt]=cnt[rt<<1]+cnt[rt<<1|1];//cnt[i]是第i号节点代表区间内有多少块数
}
void pushdown(int rt)
{
tag[rt<<1]^=tag[rt];//tag标记黑白
tag[rt<<1|1]^=tag[rt];
sum[rt<<1]=cnt[rt<<1]-sum[rt<<1];//当前节点下白变黑,黑变白
sum[rt<<1|1]=cnt[rt<<1|1]-sum[rt<<1|1];
tag[rt]=0;
}
void build (int l,int r,int rt)
{
tag[rt]=0;
if (l==r){sum[rt]=0,cnt[rt]=1;return;}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if (L<=l&&r<=R){
tag[rt]^=1;
sum[rt]=cnt[rt]-sum[rt];
return ;
}
int mid=(l+r)>>1;
if (tag[rt]) pushdown(rt);
if (L<=mid) update(L,R,l,mid,rt<<1);
if (mid+1<=R) update(L,R,mid+1,r,rt<<1|1);
pushup(rt);
}
int main()
{
int t=read();
while (t--){
n=read(),m=read();
tot = 0;
build(1,n,1);
while (m--){
int a=read(),b=read(),c=read(),d=read();
qu[++tot]=node{a,c,d};//将每个操作点拆成两个
if (b+1<=n) qu[++tot]=node{b+1,c,d};
//比如修改2<=x<=4,1<=y<=3的点转化为
//先修改2<=x<=+oo,1<=y<=3
//再修改5<=x<=+oo,1<=y<-3
//跟灯泡开关的原理一样,这样两个拆的操作与原来的操作是等价的
}
sort(qu+1,qu+1+tot);//将询问排序
/*for (int i=1;i<=tot;++i){
printf("%d %d %d\n",qu[i].x,qu[i].y1,qu[i].y2);
}*/
long long ret = 0;
int pos = 1;
for (int i=1;i<=n;++i){
while (pos<=tot&&qu[pos].x<=i){//当我们处理第i个询问时
update(qu[pos].y1,qu[pos].y2,1,n,1);
//如果还存在没有修改的操作,将它修改
pos++;
}
//printf("%d\n",sum[i]);
ret += sum[1];//如果在当前位置没有修改,那说明这一列与上一列情况一样直接加就行
}
printf("%lld\n",ret);
}
return 0;
}

  

 

2017 ICPC HongKong B:Black and White(扫描线+线段树)的更多相关文章

  1. 2017 ICPC西安区域赛 A - XOR (线段树并线性基)

    链接:https://nanti.jisuanke.com/t/A1607 题面:   Consider an array AA with n elements . Each of its eleme ...

  2. HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  3. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  4. HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)

    Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...

  5. 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树

    题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...

  6. hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

    题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...

  7. P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)

    题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...

  8. BZOJ 2584: [Wc2012]memory(扫描线+线段树)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2584 题意:给出平面n个线段,任意两个线段严格不相交,且每个线段不平行于坐标轴.移 ...

  9. [BZOJ 1218] [HNOI2003] 激光炸弹 【n logn 做法 - 扫描线 + 线段树】

    题目链接:BZOJ - 1218 题目分析 可以覆盖一个边长为 R 的正方形,但是不能包括边界,所以等价于一个边长为 R - 1 的正方形. 坐标范围 <= 5000 ,直接 n^2 的二维前缀 ...

随机推荐

  1. kafka 生产者发送消息

    KafkaProducer 创建一个 KafkaThread 来运行 Sender.run 方法. 1. 发送消息的入口在 KafkaProducer#doSend 中,但其实是把消息加入到 batc ...

  2. #1146 - Table 'phpmyadmin.pma__table_uiprefs' doesn't exist

    在使用phpmyadmin时,数据库总报错#1146 - Table ‘phpmyadmin.pma_table_uiprefs' doesn't exist 修改phpmyadmin的配置文件con ...

  3. Linux-档案权限概念

    第一欄代表這個檔案的類型與權限(permission): 這個地方最需要注意了!仔細看的話,你應該可以發現這一欄其實共有十個字元:(圖5.2.1及圖5.2.2內的權限並無關係) 圖5.2.2.檔案的類 ...

  4. [开发技巧]·如何让离线安装Python包

    [开发技巧]·如何让离线安装Python包 1.问题描述 PyPI(Python Package Index)是python官方的第三方库的仓库,所有人都可以下载第三方库或上传自己开发的库到PyPI. ...

  5. 应用安全 - PHPCMS - Joomla漏洞汇总

    Joomla 反序列化(版本低于3.4.5) CVE-2015-8562 RCE Date:October, 2019原理:https://blog.hacktivesecurity.com/inde ...

  6. python3.5+django2.0快速入门(二)

    昨天写了python3.5+django2.0快速入门(一)今天将讲解配置数据库,创建模型,还有admin的后台管理. 配置数据库 我们打开mysite/mysite/settings.py这个文件. ...

  7. 红黑树的删除操作---以JDK源码为例

    删除操作需要处理的情况: 1.删除的是红色节点,则删除节点并不影响红黑树的树高,无需处理. 2.删除的是黑色节点,则删除后,删除节点所在子树的黑高BH将减少1,需要进行调整. 节点标记: 正在处理的节 ...

  8. 在无界面centos7上部署MYSQL5.7数据库

    1. 利用xshell连接好服务后,输入 wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm 下载软件安装 ...

  9. Flash存储模块调试

    Flash存储模块 Flash存储模块之前SPI一直读deviceID有问题原因如下: 用正点原子的例程是可以的,但是转移到自己的工程项目里就不行!!原因是正点原子没有在SPI初始化里     RCC ...

  10. hdu6357 Hills And Valleys (最长不下降子序列)

    题目传送门 题意: 给你0~9的字符串,问你翻转哪个区间后使得其最长不下降子序列长度最长 思路: 因为字符是0~9,所以我们可以定义一个b数组来枚举L,R, 去和原来的字符串去求最长公共子序列长度,不 ...