Hdu 3255 Farming

题目


把价值等价成高,从价格高的开始枚举


假如i的价格>j的价格,先把价格为i的矩形更新到线段树中,然后价格为i的总价值就是面积(S1)*价格i


然后对于价格j,把i和j价格的矩形都更新到线段树中,然后此时属于j的总价值就是现在的(总面积(S2)-S1)*j;


WA了n次,一直找不到错误,今天终于找到错误了,唉,原来杭电不能用 %lld  改成%I64d就过了



#include<stdio.h>
#include<map>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
inline int input()
{
    int ret=0;
    bool IsN=0;
    char c;
    c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-') IsN=1;
        c=getchar();
    }
    while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
    return IsN?ret*-1:ret;
}
#define N 30005
map<int,int>M;
vector<int>e[4];
int k,t,n,m,p[4],pp[4];
long long li[N*2];
struct Farm
{
    int x1,x2,y1,y2,s;
}f[N];

struct Line
{
    int s,t,y,cov;
}l[N*2];
inline bool cmp(Line i,Line j)
{
    return i.y<j.y;
}

struct node
{
    int l,r,cov;
    long long len;
}root[N*15];
inline void build(int t,int x,int y)
{
    root[t].l=x;
    root[t].r=y;
    root[t].len=root[t].cov=0;
    if(x+1==y) return;
    int m=(x+y)>>1;
    build(t*2,x,m);
    build(t*2+1,m,y);
}
inline void Push(int t)
{
    if(root[t].cov>0) root[t].len=li[root[t].r]-li[root[t].l];
    else if(root[t].l+1==root[t].r) root[t].len=0;
    else root[t].len=root[t*2].len+root[t*2+1].len;
}
inline void Modefiy(int t,int x,int y,int cov)
{
    int l=root[t].l;
    int r=root[t].r;
    if(l>y||r<x) return;
    if(l>=x&&r<=y)
    {
        root[t].cov+=cov;
        Push(t);
        return;
    }
    Modefiy(t*2,x,y,cov);
    Modefiy(t*2+1,x,y,cov);
    Push(t);
}
int main()
{
    // freopen("in","r",stdin);
    // freopen("out1","w",stdout);
    t=input();
    for(int i=1;i<=t;i++)
    {
        for(int j=1;j<=3;j++) e[j].clear();
        M.clear();
        k=1;

        n=input(),m=input();
        for(int j=1;j<=m;j++)
        p[j]=input();
        for(int j=1;j<=m;j++)
        pp[j]=p[j];

        sort(p+1,p+1+m);
        for(int j=1;j<=n;j++)
        {
            f[j].x1=input();
            f[j].y1=input();
            f[j].x2=input();
            f[j].y2=input();
            f[j].s=input();
            int tag;
            for(int r=1;r<=m;r++)
            {
                if(p[r]==pp[f[j].s])
                {
                    tag=r;break;
                }
            }

            if(M[f[j].x1]==0) M[f[j].x1]=1;
            if(M[f[j].x2]==0) M[f[j].x2]=1;
            e[tag].push_back(j);
        }

        map<int,int>::iterator it=M.begin();
        for(;it!=M.end();++it)
        {
            int a=(*it).first;
            M[a]=k;
            li[k]=(long long)a;
            k++;
        }

        int num=0;
        p[0]=0;
        long long ans=0,sum=0,area;
        for(int j=m;j>=1;j--)
        {
            for(int r=0;r<e[j].size();r++)
            {
                int v=e[j][r];
                l[num].cov=1,l[num].s=f[v].x1,l[num].t=f[v].x2,l[num++].y=f[v].y1;
                l[num].cov=-1,l[num].s=f[v].x1,l[num].t=f[v].x2,l[num++].y=f[v].y2;
            }
            sort(l,l+num,cmp);
            build(1,1,k);
            area=0;
            for(int r=0;r<num-1;r++)
            {
                int a=M[l[r].s];
                int b=M[l[r].t];
                Modefiy(1,a,b,l[r].cov);
                area+=(root[1].len)*(l[r+1].y-l[r].y);
            }

            ans+=(area-sum)*(p[j]);
            sum=area;
        }
        printf("Case %d: %I64d\n",i,ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值