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;
}

 

posted @ 2018-11-08 18:01  CaptainLi  阅读(171)  评论(0编辑  收藏  举报