小喵喵和小聪聪从小就是好朋友 ,他们经常在一起玩耍 。如今小喵已经厌倦了自己居住的环境,想请小聪聪为她建一个新家。
小喵喵天生多才多艺,对多种乐器颇有研究。对于生活中常见的图形,她对圆形很感兴趣,因此小聪聪决定为她建一个圆形的新家。
我们设新家在一个平面直角坐标系上,其中新家的圆心为平面直角坐标系的原点。
小聪聪有一把神奇的剪刀,他定义了一个值m,以等分 [−pi,pi]弧度 (详见样例)。他还有一支神奇的画笔,将进行 n次“铺地毯”操作。对于第i 次“铺地毯”操作,他将设定一个半径ri,起始位置si,终止位置ti ,然后从圆心角pi*si/m到圆心角pi*ti/m这部分区域逆时针铺上一个扇形地毯。
小喵喵想到了一个奇怪的问题,她想知道有多大面积被至少铺过k次地毯。 这个问题一下就难倒了聪明的小聪聪。 现在小聪聪求助于你,你能帮他解决这个问题吗?为了方便表达 ,设答案的值为T,你只需要输出 T×2m/pi的值即可 。
Input
第一行是三个整数 n,m,k,含义 如题目描述中所述。
接下来n行, 每行描述一次铺地毯操作 。第i行有三个整数r,si,ti,含义 如 题目描述中所述。
Output
输出 一个整数 表示T×2m/pi的值。
Sample Input
3 8 2
1 -8 8
3 -7 3
5 -5 5
Sample Output
76
看题以后容易想到把圆展开变成数列,就可以用线段树维护有多少个操作覆盖了某块了
输出整数出题人真好
然后我们可以记录区间断点正负改变的方法用权值线段树找到半径值,累加
开long long
#include
#include
#define rep(i,a,b) for (i=a;i<=b;i++)
typedef long long ll;
using namespace std;
int c[800001];
struct Num {
int st,r,zf;
}a[400001];
int cnt;
int n,m,k;
int last[400001],fa[400001];
void Change(int x,int l,int r,int key,int p) {
if (l==r) {
c[x]+=p;
return;
}
int mid=l+r>>1;
if (key<=mid) Change(x*2,l,mid,key,p);
else Change(x*2+1,mid+1,r,key,p);
c[x]=c[x*2+1]+c[x*2];
}
int Query(int x,int l,int r,int key) {
if (l==r) return c[x]>=key?l:0;
int mid=l+r>>1;
return c[x*2+1]>=key?Query(x*2+1,mid+1,r,key):Query(x*2,l,mid,key-c[x*2+1]);
}
int main() {
int i,j;
scanf("%d%d%d",&n,&m,&k);
rep(i,1,n) {
int s,t,rg;
scanf("%d%d%d",&rg,&s,&t);
if (s==-m||s==m) {
a[++cnt].st=-m;a[cnt].r=rg;a[cnt].zf=1;
a[++cnt].st=t;a[cnt].r=rg;a[cnt].zf=-1;
}
else {
if (t==-m) t=m;
if (s<=t) {
a[++cnt].st=s;a[cnt].r=rg;a[cnt].zf=1;
a[++cnt].st=t;a[cnt].r=rg;a[cnt].zf=-1;
}
else {
a[++cnt].st=s;a[cnt].r=rg;a[cnt].zf=1;
a[++cnt].st=m;a[cnt].r=rg;a[cnt].zf=-1;
a[++cnt].st=-m;a[cnt].r=rg;a[cnt].zf=1;
a[++cnt].st=t;a[cnt].r=rg;a[cnt].zf=-1;
}
}
}
rep(i,1,cnt) {
j=a[i].st+m;
fa[i]=last[j];last[j]=i;
}
ll ans=0;
rep(i,-m,m-1) {
for (j=last[i+m];j;j=fa[j]) Change(1,1,100000,a[j].r,a[j].zf);
ll q=Query(1,1,100000,k);
ans+=q*q;
}
printf("%lld",ans);
}