hdu5032 树状数组

题意:

对于一个1000*1000的Mushroom,

起点在(1,1)给定一个斜率和一个x,求由斜率和x所对应的直线构成的三角形内蘑菇的总值。

每个点的对应的值为(x+A)(y+B)

每个点都有一个相对于(1,1)的一个斜率我们就按照这个斜率的大小进行排序 大的放在后面

然后我们对于每个要查询的点的斜率的进行排序

采用离线的 方法去计算我们要求的东西这样我们对于每次查询都把小于他斜率的点扔进树状数组对应的x中就可以了

然后求和

#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
using namespace std;
const int maxn =1000000+10;
typedef long long LL;

struct point
{
    int x,y;
    LL ans;
    double p;
    point(int cx=0,int cy=0,LL cans=0,double cp=0)
    {
          x=cx; y=cy; ans=cans; p=cp;
    }
}s[maxn],sc[maxn];
bool cmpp(point a, point b)
{
     return a.p<b.p;
}
bool cmpi(point a, point b)
{
     return a.y<b.y;
}
LL C[1005];
int lowbit(int x)
{
     return x&-x;
}
void add(int x,LL d)
{
    while(x<=1000)
        {
             C[x]+=d; x+=lowbit(x);
        }
}
LL sum(int x)
{
    LL ret=0;
    while(x>0)
    {
       ret+=C[x]; x-=lowbit(x);
    }
    return ret;
}

int main()
{
    int num=0;
    for(int i=1; i<=1000;i++)
         for(int j=1; j<=1000; j++)
           s[num++]=point(i,j,0,1.0*j/i);
    int cas;
    sort(s,s+num,cmpp);
    scanf("%d",&cas);
    for(int cc =1; cc<=cas; cc++)
    {
         LL A,B;
         scanf("%I64d%I64d",&A,&B);
         int m;
         scanf("%d",&m);
        for(int i=0; i<m; i++){
             int a,b,x;
             scanf("%d%d%d",&a,&b,&x);
             sc[i]=point( x,i,0,1.0*b/a );
        }
        sort(sc,sc+m,cmpp);
        int now=0;
        memset(C,0,sizeof(C));
        for(int i=0; i<m; i++)
        {
            while(now<1000000&&s[now].p<=sc[i].p){
                 add(s[now].x,1LL*(s[now].x+A)*(s[now].y+B));now++;
            }
            sc[i].ans=sum(sc[i].x);
        }
        sort(sc,sc+m,cmpi);
        printf("Case #%d:
",cc);
        for(int i=0; i<m; i++)
        {
            printf("%I64d
",sc[i].ans);
        }
    }


    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Opaser/p/4781649.html