Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树 矩阵面积并

D. Vika and Segments

Vika has an infinite sheet of squared paper. Initially all squares are white. She introduced a two-dimensional coordinate system on this sheet and drew n black horizontal and vertical segments parallel to the coordinate axes. All segments have width equal to 1 square, that means every segment occupy some set of neighbouring squares situated in one row or one column.

Your task is to calculate the number of painted cells. If a cell was painted more than once, it should be calculated exactly once.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of segments drawn by Vika.

Each of the next n lines contains four integers x1, y1, x2 and y2 ( - 109 ≤ x1, y1, x2, y2 ≤ 109) — the coordinates of the endpoints of the segments drawn by Vika. It is guaranteed that all the segments are parallel to coordinate axes. Segments may touch, overlap and even completely coincide.

Output

Print the number of cells painted by Vika. If a cell was painted more than once, it should be calculated exactly once in the answer.

Examples

input

30 1 2 11 4 1 20 3 2 3

output

8

Note

In the first sample Vika will paint squares (0, 1), (1, 1), (2, 1), (1, 2), (1, 3), (1, 4), (0, 3) and (2, 3).

题意:

  给你n天平行x,y轴的线段

  问你遍历的点有多少个

题解:

  将线段 扩展成一个长度为x * 1 的矩阵

  做一遍线段树扫描线求矩阵面积并

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")

const int N = 5e5+10, M = 5e5+11, inf = 2e9, mod = 1e9+7;
const double Pi = acos(-1.0);
typedef long long LL;
#define ls k<<1
#define rs ls | 1

int san[N], sum[N], vis[N], n, cnt = 0;
struct edge{
    int l,r,x,in;
    edge(int l = 0, int r = 0, int x = 0, int in = 0) : l(l), r(r), x(x), in(in) {}
    bool operator < (const edge &b) const {
        return x < b.x || x == b.x && in > b.in;
    }
}e[N];
int Hash(int x) {return lower_bound(san+1,san+cnt+1,x) - san;}
void push_up(int k,int ll,int rr) {
    if(vis[k]) sum[k] = san[rr + 1] - san[ll];
    else if(ll == rr) sum[k] = 0;
    else sum[k] = sum[ls] + sum[rs];
}
void update(int l,int r,int c,int ll,int rr,int k) {
    if(ll == l && rr == r) {
        vis[k] += c;
        push_up(k,ll,rr);
        return ;
    }
    int mid = (ll + rr) >> 1;
    if(r <= mid) update(l,r,c,ll,mid,ls);
    else if(l > mid) update(l,r,c,mid+1,rr,rs);
    else update(l,mid,c,ll,mid,ls), update(mid+1,r,c,mid+1,rr,rs);
    push_up(k,ll,rr);
}
int main() {
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i) {
                int x,y,xx,yy;
                scanf("%d%d%d%d",&x,&y,&xx,&yy);
                if(x > xx) swap(x,xx);
                if(y > yy) swap(y,yy);
                xx++, yy++;
                san[++cnt] = y;
                san[++cnt] = yy;
                e[i] = edge(y,yy,x,1);
                e[i+n] = edge(y,yy,xx,-1);
        }

        sort(san+1,san+cnt+1);
        cnt = unique(san + 1, san + cnt + 1) - san - 1;

        int m = n << 1;
        sort(e+1,e+m+1);

        LL ans = 0;
        for(int i = 1; i <= m; ++i) {
            int l = Hash(e[i].l);
            int r = Hash(e[i].r) - 1;
            if(l <= r) update(l,r,e[i].in,1,m,1);
            ans += 1LL * sum[1] * (e[i+1].x - e[i].x);
        }
        cout<<ans<<endl;
}
时间: 2024-12-28 05:42:55

Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树 矩阵面积并的相关文章

Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题是线段树成段更新,但是不能直接更新,不然只能一个数一个数更新.这样只能把每个数存到一个数组中,长度大概是20吧,然后模拟二进制的位操作.仔细一点就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath>

Codeforces Round #207 (Div. 1) A. Knight Tournament (线段树离线)

题目:http://codeforces.com/problemset/problem/356/A 题意:首先给你n,m,代表有n个人还有m次描述,下面m行,每行l,r,x,代表l到r这个区间都被x所击败了(l<=x<=r),被击败的人立马退出游戏让你最后输出每个人是被谁击败的,最后那个胜利者没被 人击败就输出0 思路:他的每次修改的是一个区间的被击败的人,他而且只会记录第一次那个被击败的人,用线段树堕落标记的话他会记录最后一次的,所以我们倒着来修改, 然后因为那个区间里面还包含了自己,在线段

Codeforces Round #590 (Div. 3) D. Distinct Characters Queries(线段树, 位运算)

链接: https://codeforces.com/contest/1234/problem/D 题意: You are given a string s consisting of lowercase Latin letters and q queries for this string. Recall that the substring s[l;r] of the string s is the string slsl+1-sr. For example, the substrings

Codeforces Round #337 (Div. 2) B. Vika and Squares 水题

B. Vika and Squares Vika has n jars with paints of distinct colors. All the jars are numbered from 1 to n and the i-th jar contains ai liters of paint of color i. Vika also has an infinitely long rectangular piece of paper of width 1, consisting of s

Codeforces Round #310 (Div. 1) C. Case of Chocolate (线段树)

题目地址:传送门 这题虽然是DIV1的C..但是挺简单的..只要用线段树分别维护一下横着和竖着的值就可以了,先离散化再维护.每次查找最大的最小值<=tmp的点,可以直接在线段树里搜,也可以二分去找. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.

Codeforces Round #225 (Div. 2)---E. Propagating tree(时间戳+线段树)

Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numbered from 1 to n, each node i having an initial value ai. The root of the tree is node 1. This tree has a special propert

Codeforces Round #245 (Div. 2) A - Points and Segments (easy)

水到家了 #include <iostream> #include <vector> #include <algorithm> using namespace std; struct Point{ int index, pos; Point(int index_ = 0, int pos_ = 0){ index = index_; pos = pos_; } bool operator < (const Point& a) const{ return p

Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo(矩阵)

题目链接:Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo 题意: 在一个二维方格子里有n条线段,有三种走法 (x?+?1,?y?+?1), (x?+?1,?y), or (x?+?1,?y?-?1). 现在要求每次都要在线段下行走,问你有多少种走法, 可以从(0,0)到(k,0). 题解: 考虑dp f[i][j]=f[i-1][j]+f[i-1][j+1]+f[i-1][j-1]. 由于k比较大c比较小,可以考虑用矩阵来优化

Codeforces Round #406 (Div. 2) E. Till I Collapse(主席树)

题目链接:Codeforces Round #406 (Div. 2) E. Till I Collapse 题意: 给你n个数,对于每一个k(1<=k<=n),划分区间,每个区间只能有k个不同的数字, 问最小的划分区间的个数. 题解: 用主席树倒着将数插入,对于每个区间询问第k个不同数的位置就行了. #include<bits/stdc++.h> #define F(i,a,b) for(int i=a;i<=b;i++) #define ___ freopen("