HDU 5032 Always Cook Mushroom (2014年北京赛区现场赛A题)

1.题目描述:点击打开链接

2.解题思路:本题利用极角排序+BIT解决。不过这种思路实在是不容易想到。首选把(1,1)~(1000,1000)都存入数组,并按照他们的斜率排序,然后对输入的m条询问也当做点来看待,当然,这些“点”不能和前面预处理的那些点混淆,这些点表示的是询问点,需要保存询问点的信息有:直角顶点(x,0),斜率(b/a),答案(ans),询问的id(i)。对这些询问也按照斜率由小到大排序,这样,在当前点的斜率值小于询问点的斜率时,执行add(xi,val)操作,最后的答案就是query(xi)。其实这里是一个非常微妙而精彩的做法。虽然题目中说的是第(i,j)处的val是(i+A)*(j+B),但是由于最后是一个求和的过程,因此可以等效理解成所有x值相同的val都加到x轴对应的点上,(这和《概率论》中的二维随机变量概率分布和它的边缘分布非常类似),然后,对xi求前缀和就是整个三角形的val值之和。找下一个点的答案时,直接在现有的x轴基础上继续操作即可。

3.代码:

#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<cctype>
#include<complex>
#include<functional>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define me(s)  memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair <int, int> P;

const int N=1000005;
int A,B,m;

struct Point
{
    int x,y;
    ll ans;
    double p;
}s[N],sc[N];

bool cmpp(Point a,Point b){return a.p<b.p;}
bool cmpid(Point a,Point b){return a.y<b.y;}

ll bit[1005]; //x轴的最大范围只有1000
int lowbit(int x){return x&-x;}
void add(int x,ll v)
{
    while(x<=1000)
    {
        bit[x]+=v;
        x+=lowbit(x);
    }
}

ll query(int x)
{
    ll ans=0;
    while(x>0)
    {
        ans+=bit[x];
        x-=lowbit(x);
    }
    return ans;
}

int main()
{
    int T;
    int cnt=0;
    scanf("%d",&T);
    for(int i=1;i<=1000;i++)
        for(int j=1;j<=1000;j++)
            s[cnt++]=Point{i,j,0,1.0*j/i};
    sort(s,s+cnt,cmpp);
    for(int kase=1;kase<=T;kase++)
    {
        scanf("%d%d",&A,&B);
        scanf("%d",&m);
        int a,b,x;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            scanf("%d",&x);
            sc[i]=Point{x,i,0,1.0*b/a};
        }
        sort(sc,sc+m,cmpp);
        me(bit);
        int now=0;
        for(int i=0;i<m;i++)
        {
            while(s[now].p<=sc[i].p)//只要斜率小于当前询问点的斜率,就继续执行add操作
            {
                add(s[now].x,(ll)(s[now].x+A)*(s[now].y+B));
                now++;
            }
            sc[i].ans=query(sc[i].x);
        }
        sort(sc,sc+m,cmpid);//所有询问点的答案都得到后,还按照它们的id排序
        printf("Case #%d:\n",kase);
        for(int i=0;i<m;i++)
            printf("%I64d\n",sc[i].ans);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值