题目描述

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. Windows Server 2008 R2 为用户“IIS APPPOOL\DefaultAppPool”授予的权限不足,无法执行此操作

    报表开发与部署好后,也嵌入到aspx页面中了,使用VS自带的Web服务器组件,一切正常,当部署到IIS中的时,出现了如下错误: 为用户“IIS APPPOOL\DefaultAppPool”授予的权限 ...

  2. JavaScript 变量,语句

    定义变量的方式: var   变量可以没有初始值,变量可以修改,变量可以覆盖,存在变量提升. // 变量提升机制 console.log(name)// undefined var name = &q ...

  3. 获取当前进程当前runtime加载的appdomain

    using System.Runtime.InteropServices; // Add the following as a COM reference - C:\WINDOWS\Microsoft ...

  4. WebServiceBinding属性

    属性 类型 读 写 说明 ConformsTo Wsiprofiles x x 绑定需要遵守的WS-I标准 EmitConformanceClaims Boolean     如果为true,当WSD ...

  5. lambda表达式(2)

    转:http://www.cnblogs.com/kingmoon/archive/2011/05/03/2035696.html "Lambda表达式"是一个匿名函数,是一种高效 ...

  6. CentOS7 开机启动流程

  7. 通过FSDataOutputStream向HDFS上写数据

    FSDataOutputStream,这个类重载了很多write方法,用于写入很多类型的数据:比如字节数组,long,int,char等等. 像FSDataInputStream一样,要获得FSDat ...

  8. ES6新数据类型Symbol

    Symbol 需计算字面量属性时使用 const benz = Symbol('benz'); const car = { [benz]: 'benz car' }; const info = Sym ...

  9. Buy Tickets POJ - 2828 思维+线段树

    Buy Tickets POJ - 2828 思维+线段树 题意 是说有n个人买票,但是呢这n个人都会去插队,问最后的队列是什么情况.插队的输入是两个数,第一个是前面有多少人,第二个是这个人的编号,最 ...

  10. 1.Dockerfile

    1.docker build docker build 这个动作有一个context 上下文的概念 docker build -f /path/to/a/Dockerfile .这个动作 通过 -f ...