标签:线段树
2 0 0 3 3 5 8 2 4 7 1 2 3 1 2 3 3 5 8 2 4 7 1 2 3
Case #1: 1842 1708 86 Case #2: 2901 2688 200
题目大意
给定一片蘑菇田,只有从(1,1)至(1000,1000)的整数点能产蘑菇,点(x,y)的蘑菇产量为(x+A)(y+B)
给定直角三角形的两个顶点和斜边的斜率,用(a,b)的形式给出,求该三角形内的蘑菇产量和。
解题思路
因为点最多有1000*1000=100W个,可以先求出他们斜率并排序,找到每个斜率的rank,并将询问按照x排序,将斜率离散化,从上到下,从左到右将每个点加入线段树。询问实际上就是求一个前缀和了。一边处理询问,一边处理这些点。
每次区间更新该斜率至最大的斜率(相当于添加一条权值为(x+A)(y+B)的线段),单点查询该点值。
线段树的习惯不是很好……
应该树状数组也可以过……
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;
inline int ReadInt()
{
int flag=0;
char ch=getchar();
int data=0;
while (ch<'0'||ch>'9')
{
if (ch=='-') flag=1;
ch=getchar();
}
do
{
data=data*10+ch-'0';
ch=getchar();
}while (ch>='0'&&ch<='9');
return data;
}
int A,B;
struct query
{
int p,a,b,r;
}q[100005];
LL addv[2500010];
LL ans[100005];
struct node
{
int a,b;
}sl[1000005],tmp;
int cmp2(node x,node y)
{
return (x.b*y.a<x.a*y.b);
}
int cmp(query x,query y)
{
return (x.p<y.p);
}
int cmp1(query x,query y)
{
return (x.r<y.r);
}
int t[1005][1005];
int v;
void update(int o, int L, int R,int le,int ri)
{
if (le<=L && ri>=R)
addv[o]+=v;
else {
int M = (L + R)>>1;
if (le<=M) update(o<<1,L,M,le,ri);
if (ri>M) update(o<<1|1,M+1,R,le,ri);
}
}
LL quer(int p,int x,int L,int R)
{
int M = (L + R)>>1;
LL sum=addv[x];
if (L==R) return sum;
if (p<=M) sum+=quer(p,x<<1,L,M);
if (p>M) sum+=quer(p,x<<1|1,M+1,R);
return sum;
}
int gcd(int x,int y)
{
if (x==0) return y;
return gcd(y%x,x);
}
int main()
{
int T,m,ca=0,cnt=0;
for (int i=1;i<=1000;i++)
for (int j=1;j<=1000;j++)
if (gcd(i,j)==1) {sl[++cnt].a=i;sl[cnt].b=j;}
sl[++cnt].a=1;
sl[cnt].b=1000005;
sl[0].a=1;
sl[0].b=0;
sort(sl+1,sl+1+cnt,cmp2);
for (int i=1;i<=cnt;i++)
{
for (int j=1;(sl[i].a*j<=1000)&&(sl[i].b*j<=1000);j++)
t[sl[i].a*j][sl[i].b*j]=i;
}
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&A,&B);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
q[i].r=i;
q[i].a=ReadInt();
q[i].b=ReadInt();
q[i].p=ReadInt();
}
memset(addv,0,sizeof addv);
sort(q+1,q+m+1,cmp);
int pt=0,r,c,le,ri,mid;
for (int i=1;i<=m;i++)
{
while (q[i].p>=(pt/1000+1)&&pt<1000000) {
pt++;
r=(pt-1)/1000+1;
c=(pt%1000)?(pt%1000):1000;
v=(r+A)*(c+B);
update(1,1,cnt,t[r][c],cnt);
}
tmp.a=q[i].a;
tmp.b=q[i].b;
le=0;
ri=cnt;
while (ri-le)
{
mid=(ri+le)>>1;
if (cmp2(tmp,sl[mid])==0)
le=mid+1;
else ri=mid;
}
le--;
ans[q[i].r]=quer(le,1,1,cnt);
}
printf("Case #%d:\n",++ca);
for (int i=1;i<=m;i++)
printf("%I64d\n",ans[i]);
}
return 0;
}[hdu 5032]2014北京网络赛Always Cook Mushroom 离散化+离线线段树/树状数组
标签:线段树
原文地址:http://blog.csdn.net/ahm001/article/details/39519619