1. 程式人生 > >SHOI2013 扇形面積並

SHOI2013 扇形面積並

傳送門

模擬題……然後被魔改成了小喬放技能……

考試的時候一開始想二維差分,TLE+MLE,想掃描線,沒法確定是否被覆蓋K次,之後想一維差分,以為能過,後來發現因為有可能並不是相鄰大小的半徑覆蓋一個區間,所以對半徑排序是不好使的的。

但其實這樣真的行,我們只要用平衡樹維護一下即可(順便還得啟發式合併)。

但是改變一下思路。我們通過推一波式子能明白,其實扇形啥的沒什麼用,我們把給定的s,t作為橫軸座標,其實一個點的貢獻值就是覆蓋在這個點上第k大半徑的平方。

把點推廣到區間也是一樣,所以我們其實就可以把新增一個扇形改為新增一條半徑和減少一條半徑。這樣的話,我們首先對所有扇形起始點拍一個序,之後這個區間對答案的貢獻,就是兩次端點的差值*第k大半徑的平方。

其中第k大半徑可以用權值線段樹進行維護。

之後我們就愉快的做完啦!注意如果出現s > t的情況,需要拆分成兩個區間進行維護。

看一下程式碼。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<set>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define
pb push_back #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 1000005; ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '
9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } struct mis { ll r,s,val; bool operator < (const mis &g) const { return s < g.s; } }a[M]; ll n,m,k,sum[M<<2],x,y,z,tot,ans,la,now; ll query(ll p,ll l,ll r,ll pos) { if(l == r) return l; ll mid = (l+r) >> 1; if(pos <= sum[p<<1]) return query(p<<1,l,mid,pos); else return query(p<<1|1,mid+1,r,pos - sum[p<<1]); } void modify(ll p,ll l,ll r,ll pos,ll val) { if(l == r) { sum[p] += val; return; } ll mid = (l+r) >> 1; if(pos <= mid) modify(p<<1,l,mid,pos,val); else modify(p<<1|1,mid+1,r,pos,val); sum[p] = sum[p<<1] + sum[p<<1|1]; } int main() { n = read(),m = read(),k = read(); rep(i,1,n) { x = read(),y = read(),z = read(); if(y > z) { a[++tot].r = x,a[tot].s = -m,a[tot].val = 1; a[++tot].r = x,a[tot].s = z,a[tot].val = -1; a[++tot].r = x,a[tot].s = y,a[tot].val = 1; a[++tot].r = x,a[tot].s = m,a[tot].val = -1; } else { a[++tot].r = x,a[tot].s = y,a[tot].val = 1; a[++tot].r = x,a[tot].s = z,a[tot].val = -1; } } sort(a+1,a+1+tot); rep(i,1,tot) { ll d = query(1,0,100001,now-k+1); ans += d * d * (a[i].s - la); modify(1,0,100001,a[i].r,a[i].val); now += a[i].val,la = a[i].s; } printf("%lld\n",ans); return 0; }