題目連接:https://codeforces.com/gym/101908/problem/Cc++
題意:數組
一塊正方形披薩,有 $H$ 刀是橫切的,$V$ 刀是豎切的,不存在大於等於三條直線交於一點。求最後切出多少片披薩。優化
題解:spa
橫切和豎切分開考慮,若是橫切的直線之間有 $ans_1$ 個交點,豎切的直線之間有 $ans_2$ 個交點,那麼最後答案就是 $(H+1)(V+1)+ans_1+ans_2$。code
這裏求交點個數,是用的一種比較常見的樹狀數組優化的套路。blog
還有就是時限比較緊,用vector作離散化被卡了,改用數組就行了。get
AC代碼:it
#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); }