bzoj2130: 魔塔

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2130: 魔塔相关的知识,希望对你有一定的参考价值。

Description

魔塔是一款很流行的益智类小游戏。在游戏中,你可以控制主人公在魔塔中移动,走到怪兽面前便可以和怪兽来决斗,打败怪兽后可以得到金钱,并可以通过金钱来提高自己的攻击力、防御力、血量,从而变得更强大。然而,即便你拥有再高的攻击力、防御力,可以天下无敌,但一扇小小的门就可以阻止你无法前进。在游戏中,有红、黄、蓝三种颜色的门,并对应有红、黄、蓝三种颜色的钥匙。如果你想通过一扇门,需要消耗一把对应颜色的钥匙打开这扇门,如果你没有这种颜色的钥匙,便不能通过。现在你得到一款加强版的魔塔游戏:首先,门和钥匙的颜色不再是3种,而是n种,定为1~n号颜色。对于i号颜色的钥匙你有Ki把。并且之后你不会以任何形式得到任何颜色的钥匙。在你面前有三座n层的魔塔A、B、C。每座魔塔的入口处和相邻两层之间都会有一扇门。对于每座魔塔,恰好有n扇门,并且这n扇门的颜色恰好各不相同。其中,A魔塔中通往第i层的门颜色为DoorAi。(DoorBi、DoorCi的定义与DoorAi类似)在每座魔塔的每一层都有一定数量的怪兽,但这些怪兽根本打不过强大的你,你可以不费一滴血就秒杀这些怪兽,并得到杀死他们的金钱。我们已经为你统计好,消灭A魔塔第j层中所有的怪兽,可以得到的金钱数为GoldAi。(GoldBi、GoldCi的定义与GoldAi类似)现在,就请你来决策,如何运用这些钥匙,能得到最多的金钱,并告诉我们最多能获得多少金钱。

Input

第一行一个字符(A~F),表示数据类型(在下面数据规模中有详细介绍)第二行一个整数m,表示有几组测试数据。之后给出m组数据,对于每组数据有九行: 第一行一个整数n,表示魔塔层数。第二行一个数列Ki。第三行至第五行,每行一个数列,分别为DoorA、DoorB、DoorC。第六行至第八行,每行一个数列,分别为GoldA、GoldB、GoldC。第九行为一个空行。

Output

输出应包含m行,每行一个正整数,为最大能获得的金钱数。

每个可行解的方案对应于三个魔塔各取一个前缀,可以用三个数(a,b,c)表示,因此这是一个三变量有约束的最值问题

由于每一维对答案的贡献独立,考虑从小到大枚举一个变量c,降为二维(a,b),此时约束条件有两种:a<x||b<y,a<x&&b<y,可以用平衡树(可用std::set)维护max(b)关于a的函数(非严格递减,约束条件相当于对后缀取min,每次修改后更新答案)(如果用线段树维护则需要标记回收),用堆维护当前的最优解

#include<bits/stdc++.h>
const int N=100007,RN=1e5;
char buf[N],*ptr=buf+RN;
int G(){
    if(ptr==buf+RN)fread(ptr=buf,1,RN,stdin);
    return *ptr++;
}
int _(){
    int x=0;
    if(ptr<buf+RN-100){
        while(*ptr<48)++ptr;
        while(*ptr>47)x=x*10+*ptr++-48;
    }else{
        int c=G();
        while(c<48)c=G();
        while(c>47)x=x*10+c-48,c=G();
    }
    return x;
}
void maxs(int&a,int b){if(a<b)a=b;}
void mins(int&a,int b){if(a>b)a=b;}
int n,v[3][N],p,ws[2][N],xs[N],ks[N];
std::priority_queue<int>q,qd;
struct pos{
    mutable int l,x,y;
    bool operator<(pos w)const{return x<w.x;}
    void ins()const{q.push(v[1][x]+y);}
    void del()const{qd.push(v[1][x]+y);}
}ps[N];
typedef std::set<pos>ST;
typedef ST::iterator IT;
ST st;
void cal(int x,int y){
    IT it=st.lower_bound((pos){0,x,0}),it_del;
    if(it->y<=y)return;
    int r1=-1;
    if(it->l<x){
        r1=it->x;
        it->del();
        it->x=x-1;
        it->ins();
        ++it;
    }
    for(;it!=st.end()&&it->y>y;it->del(),r1=it->x,it_del=it,++it,st.erase(it_del));
    st.insert((pos){x,r1,y}).first->ins();
}
int qmx(){
    while(qd.size()&&q.top()==qd.top())q.pop(),qd.pop();
    return q.top();
}
void work(){
    q=std::priority_queue<int>();
    qd=std::priority_queue<int>();
    st.clear();
    n=_();
    for(int i=1;i<=n;++i)ks[i]=_();
    for(int i=1;i<=n;++i)xs[i]=_();
    for(int t=0;t<2;++t){
        for(int i=1;i<=n;++i)ws[t][_()]=i;
    }
    for(int t=0;t<3;++t){
        for(int i=1;i<=n;++i)v[t][i]=v[t][i-1]+_();
    }
    st.insert((pos){0,n,v[2][n]}).first->ins();
    for(int i=1;i<=n;++i)if(ks[i]==1)cal(ws[0][i],v[2][ws[1][i]-1]);
    int ans=qmx();
    for(int i=1;i<=n;++i){
        int x=xs[i];
        int xp=ws[0][x],yp=ws[1][x];
        if(ks[x]==1){
            cal(0,v[2][yp-1]);
            cal(xp,-0x3f3f3f3f);
        }else{
            cal(xp,v[2][yp-1]);
        }
        maxs(ans,qmx()+v[0][i]);
    }
    printf("%d\n",ans);
}
int main(){
    _();
    for(int T=_();T;--T)work();
    return 0;
}

 

以上是关于bzoj2130: 魔塔的主要内容,如果未能解决你的问题,请参考以下文章

魔塔 探索500层攻略

文曲星 魔塔 攻略

魔塔65层怎么过要详细的

魔塔60层无敌攻略的65层怎么过 要详细的

@@会魔塔制作的高手请进,答对追加50分@@

2018-2019学年第一学期Java课设--魔塔