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<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\n",((ll)H+1LL)*((ll)V+1LL)+ans1+ans2); }
转载请注明出处:https://dilthey.cnblogs.com/