C*Planning
题意:有n个飞机,第i个飞机第i分钟起飞,延误一分钟损失v[i]。
现因不可抗力,前k分钟不能起飞。求一种起飞顺序方案,使总损失最低。
思路:贪心。
总损失=∑(i-a[i].id)*a[i].v=∑(i *a[i].v)-∑(a[i].id *a[i].v)
而后面的∑(a[i].id *a[i].v)是固定已知的,所以只需要∑(i *a[i].v)最小即可。
贪心方法是按a[i].v,用大根堆维护,每次取堆顶飞机起飞。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
#include<queue>
#include<math.h>
#include<vector>
using namespace std;
#define Inf 0x7fffffff
typedef long long ll;
const int N=300007;
ll ans;
struct node{
ll id,v;
bool operator <(const node &o)const{
return v<o.v;
}
}a[N];
int n,k,order[N];
priority_queue<node>q;
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i].v);
a[i].id=i;
}
for(int i=1;i<=k;i++)q.push(a[i]);
for(int i=k+1;i<=k+n;i++){
if(i<=n)q.push(a[i]);
node t=q.top();q.pop();
ans+=(i-t.id)*t.v;
order[t.id]=i;
}
cout<<ans<<endl;
for(int i=1;i<=n;i++)printf("%d ",order[i]);
}
F*Thor
题意:按照时间顺序发生q次三种事件:
1.编号x的app收到了一条信息
2.看完编号x的app的所有信息
3.看完从第一条信息开始计数的前k条信息(不是前k条未读信息,而是前k条信息)。
在每次事件结束之后输出一次当前总的未读信息数
思路:给每个app开一个队列维护,1进队,2清空队列,3判断队首是否出队。
每个元素最多进队一次出队一次,所以复杂度O(q)
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
#include<queue>
#include<math.h>
#include<vector>
using namespace std;
#define Inf 0x7fffffff
typedef long long ll;
const int N=300007;
int n,q,all,cnt,note[N],pre;
deque<int>a[N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>q;
int opt,t;
for(int i=1;i<=q;i++){
scanf("%d%d",&opt,&t);
if(opt==1){
a[t].push_back(++cnt);
note[cnt]=t;
all++;
}else
if(opt==2){
if(a[t].size()){
all-=a[t].size();
a[t].clear();
}
}else
if(t>--pre){
while(++pre<=t){
if(!a[note[pre]].size())continue;
int now=a[note[pre]].front();
if(now<=t){
a[note[pre]].pop_front();
all--;
}
}
}
cout<<all<<"\n";
}
}
G.Hard problem
题意:给n个小写字母字符串,使第i个串反转的代价为c[i],可以选择使任意串反转或不反转。求使1~n个字符串按原顺序是字典序升序排列的反转方案的最小代价。
思路:预处理s[i]反转后的字符串ss[i],dp。
设f[i][0]为第i串不反转的最小代价,f[i][1]为第i串反转的最小代价,皆可由f[i-1][0]和f[i-1][1]推出来。(!要初始化f数组为Inf)
结果是min(f[n][0],f[n][1])
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
#include<queue>
#include<math.h>
#include<vector>
using namespace std;
#define Inf 100000000000000000
typedef long long ll;
const int N=100007;
string s[N],ss[N];
ll c[N],f[N][2];
int n;
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>c[i];
for(int i=1;i<=n;i++){
cin>>s[i];
int l=s[i].length();
for(int j=0;j<l;j++)ss[i]+=s[i][l-j-1];
f[i][0]=f[i][1]=Inf;
}
f[1][0]=0;f[1][1]=c[1];
for(int i=2;i<=n;i++){
if(s[i]>=s[i-1])f[i][0]=f[i-1][0];
if(s[i]>=ss[i-1])f[i][0]=min(f[i][0],f[i-1][1]);
if(ss[i]>=s[i-1])f[i][1]=f[i-1][0]+c[i];
if(ss[i]>=ss[i-1])f[i][1]=min(f[i][1],f[i-1][1]+c[i]);
}
ll ans=min(f[n][0],f[n][1]);
if(ans==Inf)cout<<-1;else cout<<ans;
}