zoukankan      html  css  js  c++  java
  • Gym 101908C

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

    题意:

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

    题解:

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

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

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

    AC代码:

    #include<bits/stdc++.h>
    #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
    ",((ll)H+1LL)*((ll)V+1LL)+ans1+ans2);
    }
  • 相关阅读:
    C#中的异常处理
    How to: Create a Windows Communication Foundation Client
    王立平--result += &quot;{&quot;;
    Gradle增量学习建筑
    android 当屏幕截图,你如何改变屏幕内容,他们俩bitmap将合并的图像被一起显示
    惊人go语言(image网站开发)
    树莓派的演奏音符3 -- LCD1602显示文章
    Linux解析内核源代码——传输控制块诞生
    Preemption Context Switches 和 Synchronization Context Switches
    folat i = 0.1; 警告
  • 原文地址:https://www.cnblogs.com/dilthey/p/10742511.html
Copyright © 2011-2022 走看看