题目描述

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. atom超快替换文件中的tab到space

    找到开源的插件代码里缩进全部用的是tab,但公司内部的缩进要求是用space,所以需要将所有的tab替换成space. 在Atom编辑器里,选中所有内容后,点击 Edit - Lines - Auto ...

  2. 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_04 数据结构_1_数据结构_栈

    2.1 数据结构有什么用? 当你用着java里面的容器类很爽的时候,你有没有想过,怎么ArrayList就像一个无限扩充的数组,也好像链表之类 的.好用吗?好用,这就是数据结构的用处,只不过你在不知不 ...

  3. Series.str方法

    1 对dataframe的某一列用str处理后,其类型是<class 'pandas.core.strings.StringMethods'>.可以对df.['列名'].str直接进行切片 ...

  4. sql时间类型相关

    1.现在时间 NOW() 示例: select * from users where date<now() 2.时间相减 INTERVAL ' DAY 示例: ' DAY 3.timestamp ...

  5. MVC 源码系列之控制器执行(二)

    ## 控制器的执行 上一节说道Controller中的ActionInvoker.InvokeAction public virtual bool InvokeAction(ControllerCon ...

  6. Foxit_PDF_Editor(特别版)-PDF文档编辑器 V2.21 V3.1

    完全反编辑PDF,需要下载. 链接:https://pan.baidu.com/s/1QLIr_2O-WDncVm9veW8JSw 提取码:zf2a

  7. 知识点C++

    比较2个字符串的大小…… s1=s2,strcmp(s1,s2) == ; s1>s2, strcmp(s1,s2) == ; s1<s2, strcmp(s1,s2) == -; str ...

  8. SpringBoot(八) -- SpringBoot与Docker

    一.Docker简介 Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源.Docker可以让开发者打包他们的应用以及依赖到一个轻量级,可移植的容器中,然后发布到任何流行 ...

  9. CentOS6 破解登录密码

    1.重启服务器,在倒数读秒的时候按任意键,就会出现如下界面 2.按e进入grub模式,选中kernel,然后按e进入内核编辑模式 3.进入内核编辑模式后,按空格+1回车(或按空格+single回车)退 ...

  10. ajax传文件用express的multer接住

    html部分: //input type设为file <input type="file" name="file" id="fileInputE ...