weight
连个中文题目都不配吗……
题面
有 \(n\) 个砝码,重量分别为 \(a_1, a_2 · · · a_n\) ,它们的重量两两不同。
老虎有一个天平,他决定将这些砝码按某种顺序一个一个放上天平。
老虎扔了 \(n\) 次硬币,于是他给出了一个长度为 \(n\) 的由 LR 组成的串。如果这个串第 \(i\) 个位置为 L,老虎希望放完 前\(i\) 个砝码之后左边重,否则老虎希望右边重。不论任何时刻(除了刚开始)老虎都不希望两边一样重。
作为幸运观众,你需要来放这些砝码。输出一个可能的LR串。
\(n\le 10^5\)。
解法
直觉告诉说是贪心,懒得解释为什么,看那数据范围嘛。
首先对于每次操作可以分为两种情况,一种情况是此次希望的优势方和上一次不同,并赋予此次放上去的砝码以“力挽狂澜”的使命;否则我们会希望在保持此次优势方的优势的情况下尽量缩小双方的分差(毕竟差值小好控制),赋予其“浑水摸鱼”的责任。
明显力挽狂澜比浑水摸鱼需要更大的能力。所以想到统计出需要多少个力挽狂澜的砝码,并将最大的那些标记为力挽狂澜。然后按照规则贪心放置即可。
正确性:由于之前都是一些小家伙,再加之它们的中庸主义放置思路,到需要力挽狂澜之时优势方的优势一定不会大于浑水摸鱼的最大砝码,而即使是浑水摸鱼的最大砝码也比任意一个力挽狂澜要弱,所以这个策略一定能保证它在任意时刻可以扭转乾坤——一句话,构造出来的解一定是正确的。
代码
#include<cstdio>
#include<algorithm>
//#define zczc
using namespace std;
const int N=100010;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
int m,a[N];
char op[N];
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
read(m);
for(int i=1;i<=m;i++)read(a[i]);
sort(a+1,a+m+1);
scanf("%s",op+1);
int l=1,r=2;
for(int i=1;i<m;i++)if(op[i]==op[i+1])l++,r++;
long long now[2]={0,0};
for(int i=1;i<=m;i++){
bool wh=op[i]=='R';
if(i!=1&&op[i]!=op[i-1]){
printf("%d %c\n",a[r],op[i]);
now[wh]+=a[r++];
}
else{
if(now[!wh]+a[l]<=now[wh]){
printf("%d %c\n",a[l],op[i]=='R'?'L':'R');
now[!wh]+=a[l--];
}
else{
printf("%d %c\n",a[l],op[i]);
now[wh]+=a[l--];
}
}
}
return 0;
}
一如既往,万事胜意