标签:
题意是这样,给定一个1000x1000的点阵,m组询问,每次询问一个由(0,0)、(x,0)点一以及从原点出发的方向向量(a,b)构成的直角三角形包围的点的权值和。
点的权值是(x+A)(y+B),其中A,B是给定的常数
做法也很显然,将查询离线下来按照方向向量排序,之后的操作就相当于用一根端点在原点的线从x轴开始往y轴扫,不断地把扫到的点的权值加入到树状数组中。每次扫到某个查询的方向向量时,用这个三角形的底边求前缀和,记录下来就好了。
权值会爆int,注意下就好了
#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
ll bit[1010];
void update(int pos,ll val)
{
for(int i=pos;i<=1000;i+=i&-i)
bit[i]+=val;
}
ll psum(int pos)
{
ll ans=0;
for(int i=pos;i>0;i-=i&-i)
ans+=bit[i];
return ans;
}
struct Point
{
int x,y;
bool operator <(Point one)const
{
return y*one.x<=one.y*x;
}
}point[1000010];
struct Qu
{
int x,y,len,no;
bool operator <(Qu one)const
{
return ll(y*one.x)<ll(one.y*x);
}
}qu[1000010];
ll ans[1000010];
int main()
{
int n=0;
for(int i=1;i<=1000;i++)
for(int j=1;j<=1000;j++)
{
point[n].x=i;
point[n++].y=j;
}
sort(point,point+n);
int T;
scanf("%d",&T);
for(int cs=1;cs<=T;cs++)
{
int a,b,m;
scanf("%d%d%d",&a,&b,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&qu[i].x,&qu[i].y,&qu[i].len);
qu[i].no=i;
}
sort(qu,qu+m);
memset(bit,0,sizeof(bit));
for(int i=0,j=0;i<m;i++)
{
Point t;
t.x=qu[i].x;
t.y=qu[i].y;
while(j<n&&point[j]<t)
{
update(point[j].x,ll(point[j].x+a)*(point[j].y+b));
j++;
}
ans[qu[i].no]=psum(qu[i].len);
}
printf("Case #%d:\n",cs);
for(int i=0;i<m;i++)
cout<<ans[i]<<endl;
}
}Time
Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 518 Accepted Submission(s): 157
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
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/stl112514/article/details/46952839