本文主要是介绍Codeforces Round #344 (Div. 2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
C. Report
注意到每次排序的区间都是某个前缀,如果先排序了短前缀,再排序长前缀,前面的那次排序可以不用做。所以单调栈维护递减序列,排序一次最长前缀,然后逐个视情况(升序还是降序)输出。
#include <bits/stdc++.h>
#include <unordered_map> using namespace std;#define ll long longint a[200010];int ops[200010];
int sta[200010];int k=0;void print(int id,int l,int r){int len=sta[id];if(id+1<k){len-=sta[id+1];if(ops[id] == ops[0]){print(id+1,l,r-len);}else{print(id+1,l+len,r);}}if(ops[id] == ops[0]){for(int i=r-len+1;i<=r;i++){printf("%d ",a[i]);}}else{for(int i=l+len-1;i>=l;i--){printf("%d ",a[i]);}}
}int main(){int n,m;cin>>n>>m;for(int i=0;i<n;i++){scanf("%d",&a[i]);}for(int i=1;i<=m;i++){int op,r;scanf("%d%d",&op,&r);while(k>0 && (sta[k-1]<r)){k--;}ops[k] = op;sta[k] = r;k++;}sort(a,a+sta[0]);if(ops[0]==2){reverse(a,a+sta[0]);}print(0,0,sta[0]-1);for(int i=sta[0];i<n;i++){printf("%d ",a[i]);}return 0;
}
D. Messenger
无聊的题,一看就知道是KMP。通过重复次数*26+原字符,构造出新的“字符”。分类讨论单词长度为1,2和其他情况。
#include <bits/stdc++.h>
#include <unordered_map> using namespace std;#define ll long longconst int maxn = 200010;ll word[maxn];
ll text[maxn];
int _next[maxn];ll textl[maxn];
char textc[maxn];ll wordl[maxn];
char wordc[maxn];int n,m;ll ans = 0;void find_next(){_next[1]=0;int k = 0;for(int i=2;i<=m;i++){while(k && word[i]!=word[k+1]){k = _next[k];}if(word[i]==word[k+1]){_next[i] = ++k;}else{_next[i]=0;}}
}void match(){int k=0;for(int i=1;i<=n;i++){while(k && text[i]!=word[k+1]){k = _next[k];}if(text[i]==word[k+1]){k++;}if(k==m){if(wordc[0]==textc[i-m] && wordl[0]<=textl[i-m] && wordc[m+1]==textc[i+1] && wordl[m+1]<=textl[i+1]){ans++; }k = _next[k];}}
}int main(){cin>>n>>m;for(int i=1;i<=n;i++){scanf("%I64d-%c",&textl[i],&textc[i]);if(textc[i]==textc[i-1]){textl[i-1]+=textl[i];n--;i--;}text[i] = textl[i]*26LL + textc[i];}for(int i=0;i<m;i++){scanf("%I64d-%c",&wordl[i],&wordc[i]);if(wordc[i]==wordc[i-1]){wordl[i-1]+=wordl[i];m--;i--;}word[i] = wordl[i]*26LL + wordc[i]; }if(m==1){for(int i=1;i<=n;i++){if(textc[i]==wordc[0] && textl[i]>=wordl[0]){ans+=(textl[i]-wordl[0]+1);}}}else if(m==2){for(int i=1;i<n;i++){if(textc[i]==wordc[0] && textl[i]>=wordl[0]){if(textc[i+1]==wordc[1] && textl[i+1]>=wordl[1]){ans++;}}}}else{m-=2;find_next();match();}cout<<ans<<endl;return 0;
}
E. Product Sum
最优解有两种可能,某个字符往右换和往左换,原理是一样的。
不妨考虑往右换的情况,假如我把第 i 个数换到第
#include <bits/stdc++.h>
#include <unordered_map> using namespace std;#define ll long longint n;
int a[200010];
ll sum[200010];ll ans = 0;void solveR(){map<int,int> mp;for(int i=n;i>=1;i--){auto it = mp.lower_bound(a[i]);int k;if(it==mp.end()){k = n;}else{k = it->second;while(a[k]>a[i]){k--;}}mp[a[i]]=k;ll tmp = (a[i]+0LL)*(k-i) - (sum[k]-sum[i]);ans = max(tmp,ans);}
}void solveL(){map<int,int> mp;for(int i=1;i<=n;i++){auto it = mp.upper_bound(a[i]);int k;if(it==mp.begin()){k = 1;}else{it--;k = it->second;while(a[k]<a[i]){k++;}}mp[a[i]]=k;ll tmp = -(a[i]+0LL)*(i-k) + (sum[i-1]-sum[k-1]);ans = max(tmp,ans);}
}int main(){cin>>n;ll ans0 = 0;for(int i=1;i<=n;i++){scanf("%d",&a[i]);ans0+=(a[i]+0LL)*(i);}//calc sumfor(int i=1;i<=n;i++){sum[i] = sum[i-1] + a[i];}solveR();solveL();cout<<ans+ans0<<endl;return 0;
}
这篇关于Codeforces Round #344 (Div. 2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!