1. 程式人生 > >Gym - 101908C Pizza Cutter —— 樹狀陣列,橫豎切割平面

Gym - 101908C Pizza Cutter —— 樹狀陣列,橫豎切割平面

Grandpa Giuseppe won a professional pizza cutter, the kind of type reel and, to celebrate, baked a rectangle pizza to his grandchildren! He always sliced his pizzas into pieces by making cuts over continuous lines, not necessarily rectilinear, of two types: some begin at the left edge of the pizza, follow continuously to the right and end up in the right edge; other start on lower edge, follow continuously up and end up on the top edge. But Grandpa Giuseppe always followed a property: two cuts of the same type would never intersect. Here is an example with 4 cuts, two of each type, in the left part of the figure, which divide the pizza in 9 pieces.

It turns out that Grandpa Giuseppe simply loves geometry, topology, combinatorics and stuff; so, he decided to show to his grandchildren who could get more pieces with the same number of cuts if cross cuts of the same type were allowed. The right part of the figure shows, for example, that if the two cuts of the type that go from left to right could intercept, the pizza would be divided into 10 pieces.

Grandpa Giuseppe ruled out the property, but will not make random cuts. In addition to being one of the two types, they will comply with the following restrictions:

Two cuts have at most one intersection point and, if they have, it is because the cuts cross each other at that point;
Three cuts do not intersect in a single point;
Two cuts do not intersect at the border of the pizza;
A cut does not intercept a pizza corner.
Given the start and end points of each cut, your program should compute the number of resulting pieces from the cuts of Grandfather Giuseppe.

Input
The first line of the input contains two integers X and Y, (1≤X,Y≤109), representing the coordinates (X,Y) of the upper-right corner of the pizza. The lower left corner has always coordinates (0,0). The second line contains two integers H and V, (1≤H,V≤105), indicating, respectively, the number of cuts ranging from left to right and the number of cuts ranging from bottom to top. Each of the following lines H contains two integers Y1 and Y2, a cut that intercepts the left side with y-coordinate Y1 and the right side at y-coordinate Y2. Each of the following V lines contains two integers X1 and X2, a cut that intercept the bottom side at x-coordinate X1 and the upper side at x-coordinate X2.

Examples
Input
3 4
3 2
1 2
2 1
3 3
1 1
2 2
Output
13
Input
5 5
3 3
2 1
3 2
1 3
3 4
4 3
2 2
Output
19
Input
10000 10000
1 2
321 3455
10 2347
543 8765
Output
6

題意:

給你一個平面,n條橫的線,n條豎的線,保證:
1。兩條線最多隻有一個交點
2.沒有三條線交於一點
3.任意兩條線不交於邊界
4.任意線不經過角
問你這些線把這個平面分成幾部分

題解:

切割平面的總和是橫:1+與這條線相交的線的數量+縱:1+與這條線相交線的數量+橫的線的數量*縱的線的數量+1
之後就可以用樹狀陣列做了,一邊排序,另一邊加到樹狀數組裡就可以得到有多少線與這個線相交。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=4e5+5;
struct cross//橫
{
    int lef,rig;
    bool operator< (const cross& a)const
    {
        return lef<a.lef;
    }
}cro[N];
struct roll
{
    int top,down;
    bool operator< (const roll& a)const
    {
        return top<a.top;
    }
}rol[N];
ll heng[N],shu[N];
int lsc[N],lsr[N];
int lowbit(int x)
{
    return x&(-x);
}
void across(int x)
{
    for(int i=x;i;i-=lowbit(i))
        heng[i]++;
}
void aroll(int x)
{
    for(int i=x;i;i-=lowbit(i))
        shu[i]++;
}
ll qcross(int x)
{
    ll ans=0;
    for(int i=x;i<N;i+=lowbit(i))
        ans+=heng[i];
    return ans;
}
ll qroll(int x)
{
    ll ans=0;
    for(int i=x;i<N;i+=lowbit(i))
        ans+=shu[i];
    return ans;
}
int main()
{
    int c,r;
    scanf("%d%d",&c,&r);
    int n,m;
    scanf("%d%d",&n,&m);
    int ctr=0,ctc=0;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&cro[i].lef,&cro[i].rig),lsc[++ctc]=cro[i].lef,lsc[++ctc]=cro[i].rig;
    for(int i=1;i<=m;i++)
        scanf("%d%d",&rol[i].down,&rol[i].top),lsr[++ctr]=rol[i].down,lsr[++ctr]=rol[i].top;
    sort(lsc+1,lsc+1+ctc),sort(lsr+1,lsr+1+ctr);
    int allc=unique(lsc+1,lsc+1+ctc)-lsc-1,allr=unique(lsr+1,lsr+1+ctr)-lsr-1;
    for(int i=1;i<=n;i++)
    {
        cro[i].lef=lower_bound(lsc+1,lsc+1+allc,cro[i].lef)-lsc;
        cro[i].rig=lower_bound(lsc+1,lsc+1+allc,cro[i].rig)-lsc;
    }
    sort(cro+1,cro+1+n);
    for(int i=1;i<=m;i++)
    {
        rol[i].top=lower_bound(lsr+1,lsr+1+allr,rol[i].top)-lsr;
        rol[i].down=lower_bound(lsr+1,lsr+1+allr,rol[i].down)-lsr;
    }
    sort(rol+1,rol+1+m);
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        ans+=1+qcross(cro[i].rig);
        across(cro[i].rig);
    }
    for(int i=1;i<=m;i++)
    {
        ans+=1+qroll(rol[i].down);
        aroll(rol[i].down);
    }
    ans+=1+(ll)n*m;
    printf("%lld\n",ans);
    return 0;
}