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: 魔塔的主要内容,如果未能解决你的问题,请参考以下文章