Codeforces 853C(掃描線+樹狀數組)

Ilya is sitting in a waiting area of Metropolis airport and is bored of looking at time table that shows again and again that his plane is delayed. So he took out a sheet of paper and decided to solve some problems.

First Ilya has drawn a grid of size n × n and marked n squares on it, such that no two marked squares share the same row or the same column. He calls a rectangle on a grid with sides parallel to grid sides beautiful if exactly two of its corner squares are marked. There are exactly n·(n - 1) / 2 beautiful rectangles.

Ilya has chosen q query rectangles on a grid with sides parallel to grid sides (not necessarily beautiful ones), and for each of those rectangles he wants to find its beauty degree. Beauty degree of a rectangle is the number of beautiful rectangles that share at least one square with the given one.

Now Ilya thinks that he might not have enough time to solve the problem till the departure of his flight. You are given the description of marked cells and the query rectangles, help Ilya find the beauty degree of each of the query rectangles.

Input
The first line of input contains two integers n and q (2 ≤ n ≤ 200 000, 1 ≤ q ≤ 200 000) — the size of the grid and the number of query rectangles.

The second line contains n integers p1, p2, …, pn, separated by spaces (1 ≤ pi ≤ n, all pi are different), they specify grid squares marked by Ilya: in column i he has marked a square at row pi, rows are numbered from 1 to n, bottom to top, columns are numbered from 1 to n, left to right.

The following q lines describe query rectangles. Each rectangle is described by four integers: l, d, r, u (1 ≤ l ≤ r ≤ n, 1 ≤ d ≤ u ≤ n), here l and r are the leftmost and the rightmost columns of the rectangle, d and u the bottommost and the topmost rows of the rectangle.

Output
For each query rectangle output its beauty degree on a separate line.

Examples
input

2 3
1 2
1 1 1 1
1 1 1 2
1 1 2 2

output

1
1
1

input

4 2
1 3 2 4
4 1 4 4
1 1 2 3

output

3
5

題目大意:在一個n行n列的矩陣中,有n個點,每一列有一個點,然後有m次詢問,每一次詢問中,給出一個矩形,問由矩陣中的n個點組成的矩形中有多少個矩形與給定的矩形是相交的。
解題思路:將矩形的四條邊無限延長,然後就可以分成9個部分,然後就畫圖看出這些排列組合是我們所求的答案。我們求每個部分的點的數量可以使用樹狀數組維護,對於y排序,然後將x加入樹狀數組,我們就可以算出y小於等於一個值時,x小於等於一個值的答案啦。然後再容斥一下就可以算出每個部分的答案啦。
代碼:

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <bitset>
#include <queue>
using namespace std;
#define int long long
#define ls root<<1
#define rs root<<1|1
const int maxn = 5e5 + 7;
const int inf = 0x3f3f3f3f;
int a[maxn][11], f[maxn];
struct Node
{
    int x, y;
    bool operator <(Node a)const {
        return y < a.y;
    }
} node[maxn];
struct Edge
{
    int x, y, pos, id;
    bool operator <(Edge a)const{
        return y < a.y;
    }
} e[maxn << 2];
int sum[maxn], n, m;
void add(int x)
{
    while (x <= n){
        sum[x]++;
        x += (x & -x);
    }
}
int ask(int x)
{
    int ans = 0;
    while(x){
        ans += sum[x];
        x -= (x & -x);
    }
    return ans;
}
int cnt, high[10], tot;
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n;i++){
        int y;
        cin >> y;
        node[i] = Node{i, y};
    }
    for (int i = 1; i <= m;i++){
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        e[++cnt] = Edge{x1 - 1, y1 - 1, 1, i};
        e[++cnt] = Edge{x1 - 1, y2, 2, i};
        e[++cnt] = Edge{x1 - 1, n, 3, i};
        e[++cnt] = Edge{x2, y1 - 1, 4, i};
        e[++cnt] = Edge{x2, y2, 5, i};
        e[++cnt] = Edge{x2, n, 6, i};
        e[++cnt] = Edge{n, y1 - 1, 7, i};
        e[++cnt] = Edge{n, y2, 8, i};
        e[++cnt] = Edge{n, n, 9, i};
    }
    sort(node + 1, node + 1 + n), sort(e + 1, e + cnt + 1);
    for (int i = 1, j = 1; i <= cnt; i++){
        while(j<=n && node[j].y<=e[i].y)
            add(node[j++].x);
        a[e[i].id][e[i].pos] = ask(e[i].x);
    }
    for (int i = 1; i <= m;i++){
        tot = 0;
        high[1] = a[i][1];
        high[2] = a[i][2] - a[i][1];
        high[3] = a[i][3] - a[i][2];
        high[4] = a[i][4] - a[i][1];
        high[5] = a[i][5] - a[i][4] - a[i][2] + a[i][1];
        high[6] = a[i][6] - a[i][5] - a[i][3] + a[i][2];
        high[7] = a[i][7] - a[i][4];
        high[8] = a[i][8] - a[i][7] - a[i][5] + a[i][4];
        high[9] = a[i][9] - a[i][8] - a[i][6] + a[i][5];
        tot += high[5] * (n-high[5]);
        tot += high[5] * (high[5] - 1) / 2;
        tot += high[1] * (high[6] + high[8] + high[9]);
        tot += high[2] * (high[4] + high[6] + high[7] + high[8] + high[9]);
        tot += high[3] * (high[4] + high[7] + high[8]);
        tot += high[4] * (high[6] + high[8] + high[9]);
        tot += high[6] * (high[8] + high[7]);
        cout << tot << endl;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章