Fountains CodeForces

来源:互联网 发布:五星体育网络源 编辑:程序博客网 时间:2024/06/04 22:50

点击打开链接

三种情况

1 硬币类 钻石类 各一

2 硬币类选其二

3 钻石类选其二

处理后两者 要先按价格排序 再枚举每一个喷泉的价格 通过剩余的钱数二分确定另外一个喷泉该在什么价格区间 通过RMQ或线段树找最值


1.RMQ算法

#include <bits/stdc++.h>#define N 1e9using namespace std;
struct node{    int b;    int p;};
node foun1[100010],foun2[100010];int dp1[100010][20],dp2[100010][20];int pre1[100010],pre2[100010];int n,c,d,num1,num2;int sum1,sum2,sum3,ans;
int cmp(node n1,node n2){    return n1.p<n2.p;}
void calculate();
int main(){    int i,b,p;    char ch[2];    while(scanf("%d%d%d",&n,&c,&d)!=EOF)    {        num1=0,num2=0;        for(i=1;i<=n;i++)        {            scanf("%d %d %s",&b,&p,ch);            if(ch[0]=='C')            {                num1++;                foun1[num1].b=b;                foun1[num1].p=p;            }            else            {                num2++;                foun2[num2].b=b;                foun2[num2].p=p;            }        }        calculate();        printf("%d\n",ans);    }    return 0;}
void calculate(){    int i,j,t,l,r,k,flag;    sort(foun1+1,foun1+num1+1,cmp);    sort(foun2+1,foun2+num2+1,cmp);    for(i=1;i<=num1;i++)    {        pre1[i]=foun1[i].p;    }    for(i=1;i<=num2;i++)    {        pre2[i]=foun2[i].p;    }    pre1[num1+1]=N,pre2[num2+1]=N;
    for(i=1;i<=num1;i++)    {        dp1[i][0]=foun1[i].b;    }    for(j=1;(1<<j)<=num1;j++)    {        for(i=1;i+(1<<j)-1<=num1;i++)        {            dp1[i][j]=max(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]);        }    }
    for(i=1;i<=num2;i++)    {        dp2[i][0]=foun2[i].b;    }    for(j=1;(1<<j)<=num2;j++)    {        for(i=1;i+(1<<j)-1<=num2;i++)        {            dp2[i][j]=max(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]);        }    }
    ans=0;    sum1=0;    if(num1>=2&&foun1[1].p+foun1[2].p<=c)    {        for(i=1;i<=num1;i++)        {            l=i+1;            if(l==num1+1) continue;            r=upper_bound(pre1+l,pre1+num1+2,c-foun1[i].p)-pre1-1;            if(r==l-1) continue;            k=log((double)(r-l+1))/log(2.0);            t=max(dp1[l][k],dp1[r-(int)(pow(2,k))+1][k]);            if(t+foun1[i].b>sum1) sum1=t+foun1[i].b;        }    }
    sum2=0;    if(num2>=2&&foun2[1].p+foun2[2].p<=d)    {        for(i=1;i<=num2;i++)        {            l=i+1;            if(l==num2+1) continue;            r=upper_bound(pre2+l,pre2+num2+2,d-foun2[i].p)-pre2-1;            if(r==l-1) continue;            k=log((double)(r-l+1))/log(2.0);            t=max(dp2[l][k],dp2[r-(int)(pow(2,k))+1][k]);            if(t+foun2[i].b>sum2) sum2=t+foun2[i].b;        }    }    ans=max(sum1,sum2);
    sum3=0,flag=0;    for(i=1;i<=num1;i++)    {        if(foun1[i].p<=c)        {            if(foun1[i].b>flag)            {                flag=foun1[i].b;            }        }        else break;    }    if(flag!=0)    {        sum3+=flag,flag=0;        for(i=1;i<=num2;i++)        {            if(foun2[i].p<=d)            {                if(foun2[i].b>flag)                {                    flag=foun2[i].b;                }            }            else break;        }        if(flag!=0) sum3+=flag;        else sum3=0;    }
    ans=max(ans,sum3);    return;}

2 线段树
#include <bits/stdc++.h>using namespace std;#define N 1e9struct node1{    int b;    int p;};struct node2{    int l;    int r;    int val;};node1 foun1[100010],foun2[100010];node2 tree[800010];int pre[100010];int n,c,d,num1,num2,cnt,maxx;int cmp(node1 n1,node1 n2){    return n1.p<n2.p;}void calculate(node1* foun,int num,int fund);void pushup(int cur);void build(node1* foun,int l,int r,int cur);int query(int ll,int rr,int cur);int main(){    int i,j,p,b,flag,sum;    char ch[2];    while(scanf("%d%d%d",&n,&c,&d)!=EOF)    {        num1=0,num2=0;        for(i=1;i<=n;i++)        {            scanf("%d %d %s",&b,&p,ch);            if(ch[0]=='C')            {                num1++;                foun1[num1].b=b;                foun1[num1].p=p;            }            else            {                num2++;                foun2[num2].b=b;                foun2[num2].p=p;            }        }        maxx=0;        if(num1>=2) calculate(foun1,num1,c);        if(num2>=2) calculate(foun2,num2,d);        sum=0,flag=0;        for(i=1;i<=num1;i++)        {            if(foun1[i].p<=c)            {                if(foun1[i].b>flag)                {                    flag=foun1[i].b;                }            }            else break;        }        if(flag!=0)        {            sum+=flag,flag=0;            for(i=1;i<=num2;i++)            {                if(foun2[i].p<=d)                {                    if(foun2[i].b>flag)                    {                        flag=foun2[i].b;                    }                }                else break;            }            if(flag!=0) sum+=flag;            else sum=0;        }        maxx=max(maxx,sum);        printf("%d\n",maxx);    }    return 0;}void calculate(node1* foun,int num,int fund){    int i,l,r;    sort(foun+1,foun+num+1,cmp);    cnt=1;    build(foun,1,num,1);    for(i=1;i<=num;i++)    {        pre[i]=foun[i].p;    }    pre[num+1]=N;    for(i=1;i<=num;i++)    {        l=i+1;        if(l==num+1) break;        r=upper_bound(pre+l,pre+num+2,fund-pre[i])-pre-1;        if(r==l-1) break;        maxx=max(maxx,query(l,r,1)+foun[i].b);    }    return;}void pushup(int cur){    tree[cur].val=max(tree[cur*2].val,tree[cur*2+1].val);    return;}void build(node1* foun,int l,int r,int cur){    int m;    tree[cur].l=l;    tree[cur].r=r;    tree[cur].val=0;    if(l==r)    {        tree[cur].val=foun[cnt++].b;        return;    }    m=(l+r)/2;    build(foun,l,m,cur*2);    build(foun,m+1,r,cur*2+1);    pushup(cur);    return;}int query(int ll,int rr,int cur){    int m,ans;    if(ll<=tree[cur].l&&tree[cur].r<=rr)    {        return tree[cur].val;    }    m=(tree[cur].l+tree[cur].r)/2,ans=0;    if(ll<=m)    {        ans=max(ans,query(ll,rr,cur*2));    }    if(rr>=m+1)    {        ans=max(ans,query(ll,rr,cur*2+1));    }    return ans;}

原创粉丝点击