Gym 101908C - Pizza Cutter - [树状数组]

题目链接:https://codeforces.com/gym/101908/problem/C

 

题意:

一块正方形披萨,有 $H$ 刀是横切的,$V$ 刀是竖切的,不存在大于等于三条直线交于一点。求最后切出多少片披萨。

 

题解:

横切和竖切分开考虑,如果横切的直线之间有 $ans_1$ 个交点,竖切的直线之间有 $ans_2$ 个交点,那么最后答案就是 $(H+1)(V+1)+ans_1+ans_2$。

这里求交点个数,是用的一种比较常见的树状数组优化的套路。

还有就是时限比较紧,用vector做离散化被卡了,改用数组就好了。

 

AC代码:

#include
#define mk make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=1e5+10;

int X,Y;
int H,V;

int v[2*maxn],tot;
inline int getID(int x)
{
    return lower_bound(v,v+tot,x)-v+1;
}

struct Line{
    int l,r;
    bool operator<(const Line& o)const {
        return l>o.l;
    }
}lines[maxn];

struct _BIT{
    int N,C[2*maxn];
    inline int lowbit(int x){return x&(-x);}
    void init(int n) //初始化共有n个点
    {
        N=n;
        for(int i=1;i<=N;i++) C[i]=0;
    }
    void add(int pos,int val) //在pos点加上val
    {
        while(pos<=N)
        {
            C[pos]+=val;
            pos+=lowbit(pos);
        }
    }
    int ask(int pos) //查询1~pos点的和
    {
        int ret=0;
        while(pos>0)
        {
            ret+=C[pos];
            pos-=lowbit(pos);
        }
        return ret;
    }
}BIT;

ll solve(int UP)
{
    BIT.init(tot+3);
    ll res=0;
    for(int i=1;i<=UP;i++)
    {
        res+=(ll)BIT.ask(lines[i].r-1);
        BIT.add(lines[i].r,1);
    }
    return res;
}

int main()
{
    scanf("%d%d%d%d",&X,&Y,&H,&V);

    tot=0;
    for(int i=1;i<=H;++i)
    {
        scanf("%d%d",&lines[i].l,&lines[i].r);
        v[tot++]=lines[i].l;
        v[tot++]=lines[i].r;
    }
    sort(v,v+tot); unique(v,v+tot);
    for(int i=1;i<=H;i++) lines[i].l=getID(lines[i].l), lines[i].r=getID(lines[i].r);
    sort(lines+1,lines+H+1);
    ll ans1=solve(H);

    tot=0;
    for(int i=1;i<=V;i++)
    {
        scanf("%d%d",&lines[i].l,&lines[i].r);
        v[tot++]=lines[i].l;
        v[tot++]=lines[i].r;
    }
    sort(v,v+tot); unique(v,v+tot);
    for(int i=1;i<=V;i++) lines[i].l=getID(lines[i].l), lines[i].r=getID(lines[i].r);
    sort(lines+1,lines+V+1);
    ll ans2=solve(V);

    printf("%I64d\n",((ll)H+1LL)*((ll)V+1LL)+ans1+ans2);
}

 

你可能感兴趣的:(Gym 101908C - Pizza Cutter - [树状数组])