• 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);
    }
  • 相关阅读:
    (字典树)Revenge of Fibonacci -- HDU -- 4099
    (字符串 KMP)Blue Jeans -- POJ -- 3080:
    (广搜)聪明的打字员 -- POJ --1184
    (线段树 点更新 区间求和)lightoj1112
    Jquery弹窗插件Lhgdialog的用法
    SQL Server数据库大型应用解决方案总结
    C# 使用XmlDocument类对XML文档进行操作
    反射实例【转】
    如何使用dynamic
    [C#]DataTable常用操作总结
  • 原文地址:https://www.cnblogs.com/dilthey/p/10742511.html
Copyright © 2020-2023  润新知