【题解】【CF1271D Portals】
Analysis
自己想了一个与题解都不同的做法。题解主要是两个做法,一个是反悔贪心,一个是dp,都是基于“每个城堡尽量在晚的时候控制”的思路做的。想学点这
我是对士兵进行思考的。
- 首先发现题目中攻打下一个城市需要的士兵数实际上没有考虑到后面的影响,我们很容易可以倒着做一遍,将考虑到后面城市影响的最少士兵数计算出来。
d[i]表示要把i及之后的城市全打下来,至少从i-1排出多少城市。c[i]表示原最少所需士兵数,a[i]表示打下i后新获得的士兵数。
d[n]=c[n];
for(int i=n;i;--i)
{
d[i-1]=max(c[i-1],d[i]-a[i-1]);
}
同时,判断d[1]与初始人数k的关系即可判断是否有解。
2. 我们考虑每次从城市i到i+1时,只把必须的士兵数给i+1,剩余的士兵留下来另做打算。因为士兵在的城市越早,他的“选择”越多:可以随时让他跟着大部队一起走,因此包含之后的城市的所有选择。
设w[i]表示城市i可自由支配的士兵数,则w[i]=(i-1派给他的士兵数)+a[i](新得的士兵数)-d[i+1](它要派出去的士兵数)
w[1]=k+a[1]-d[2];
for(int i=2;i<=n;++i) w[i]=d[i]+a[i]-d[i+1];
注意第一个城市从之前继承k个士兵,其余城市继承d[i]个。
3. 考虑贪心,从后向前扫描每个城市,同时维护这个城市可到达的其他城市集合,那么这个集合的大小是单增的,我们每次尽量把城市的士兵分完(除非已经把当前城市能到的城市全都占满),每次优先让士兵去重要值大的城市。
证明:如果当前士兵u不去重要值最大的城市x,而是去一个较小的城市y,如果后来x没有被占领的话一定不优,如果x被后面的士兵v占领了,因为可达集合是单增的,因此v一定可以占领y,所以令u占领x,v占领y,答案不会变差。
具体实现用一个堆维护重要值,和一个vis判重即可。
for(int i=n;i;--i)
{
if(vis[i]==0) q.push(b[i]),vis[i]=1;
for(int j=0;j<v[i].size();++j){
int y=v[i][j];if(vis[y]) continue;
q.push(b[y]);vis[y]=1;
}
while(q.size()&&w[i]){
w[i]--;ans+=q.top();q.pop();
}
}
完整代码
#include<bits/stdc++.h>
using namespace std;
//#define int long long
inline int read()
{
register int x=0,w=1;
register char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') {w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=~(x-1);
if(x>9) write(x/10);
putchar('0'+x%10);
}
const int N=5010;
int n,m,k,c[N],a[N],b[N],w[N],d[N];
vector<int>v[N];
int vis[N];
priority_queue<int>q;
int ans;
signed main()
{
n=read();m=read();k=read();
for(int i=1;i<=n;++i){
c[i]=read();a[i]=read();b[i]=read();
}
d[n]=c[n];
for(int i=n;i;--i)
{
d[i-1]=max(c[i-1],d[i]-a[i-1]);
}
if(d[1]>k){
puts("-1");return 0;
}
w[1]=k+a[1]-d[2];
for(int i=2;i<=n;++i) w[i]=d[i]+a[i]-d[i+1];
for(int i=1;i<=m;++i)
{
int x=read(),y=read();
v[x].push_back(y);
}
for(int i=n;i;--i)
{
if(vis[i]==0) q.push(b[i]),vis[i]=1;
for(int j=0;j<v[i].size();++j){
int y=v[i][j];if(vis[y]) continue;
q.push(b[y]);vis[y]=1;
}
while(q.size()&&w[i]){
w[i]--;ans+=q.top();q.pop();
}
}
write(ans);
return 0;
}
/*
4 3 0
0 1 1
0 0 10
0 1 100
0 2 1000
3 2
4 3
4 2
*/

浙公网安备 33010602011771号