这场AB很快就秒了,C没读懂题,D也没读懂,开了E题,wa了2发之后休息了一会开始做CD,C很简单过了,然后继续怼E,wa了1发,开始看F然后开D,最后DE切换,后来发现Dwa3发是爆了int。E一直想拿并查集做懒得写tarjan,补题的时候发现了并查集的bug,最后还是拿了tarjan写。F题场后发现居然可以这样dp。
总结:
- 读不懂切题挺好的。
- 还是要注意ll
- D的前两wa,一个是TLE的算法没注意看数据,一个是没写好一个地方,也记录错误cnt里。
题解:
A.
题意:n个数,从两头删除权值<=k的数,问最多能删几个。(n,k都很小
思路:一开始写的双指针,后来写了一半想写deque了。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
int main(){
IO;
int n,k;cin>>n>>k;
deque<int>q;forn(i,n){
int x;cin>>x;
q.push_back(x);
}int cnt = 0;
while(!q.empty()){if(q.front()>k&&q.back()>k)break;
if(q.front()<=k) cnt++,q.pop_front();
else if(q.back()<=k) cnt++,q.pop_back();
}
cout << cnt <<'
';
return 0;
}
B
題意:一個字符串長度n,設x屬於1-n,如果n可以被x整除那麽把1-x位倒過來。按因子逆序的方式倒過來的字符串是加密字符串,讓你解碼。(n很小
思路:暴力
代碼:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
int main(){
IO;
int n;string s;cin>>n>>s;
for1(i,n)if(n%i==0){
string t = "";
for(int j = i-1;j>=0;j--){
t+=s[j];
}
for(int j = i;j<n;j++){
t+=s[j];
}
s = t;
}
cout << s<<'
';
return 0;
}
C
題意:長度為n的字符串,k次操作,先按字典序刪除字符再按1-n刪除的順序刪除k次,問之後最後字符串變成什麽。
思路:圖方便用的multiset
代碼:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
int main(){
IO;
multiset<pair<char,int> >s;
multiset<pair<int,char> > s2;
int n,k;cin>>n>>k;
forn(i,n){
char c;cin>>c;
s.insert({c,i});
}
forn(i,k){
s.erase(s.begin());
}
for(auto x:s){
s2.insert({x.second,x.first});
}
for(auto x:s2) cout <<x.second;
return 0;
}
D.
題意:n被m整除,給你n個數,一次操作可以讓a[i]++,讓你使這n個數通過最小的操作次數使得每個a[i]%m后的數的cnt==n/m
思路:lowerbound
代碼:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(ll i=0;i<n;i++)
#define for1(i,n) for(ll i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const ll inf = 0x3f3f3f3f;
map<ll,ll>mp;
int main(){
IO;
ll n,m;cin>>n>>m;
ll lim = n/m;
vector<ll>a(n);
set<ll>s;
forn(i,m) s.insert(i);
s.insert(inf);
ll cnt = 0;
forn(i,n){
cin>>a[i];
ll x = a[i]%m;
if(mp[x]<lim) mp[x]++;
else{
if(*s.lower_bound(x)!=inf){
ll y = *s.lower_bound(x);
cnt+=y-x;
a[i]+=y-x;
mp[y]++;
x = y;
}else{
ll y = *s.lower_bound(0);
cnt+=m-(x-y);
a[i]+=m-(x-y);
mp[y]++;
x = y;
}
}
if(mp[x]==lim) s.erase(x);
}cout<<cnt<<'
';
for(auto x:a)cout<<x<<' ';
return 0;
}
E.
題意:给定三个正整数N,M,S,N表示图中一共有N个节点,M表示有M条边,S是N个节点中的一个,并给定M条单向边,求至少需要加几条单向边,使得从S出发,能够到达所有其他节点。
思路:我是tarjan縮點完找入度為0的點
代碼:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int maxn = 5005;
int low[maxn],dfn[maxn],id,color[maxn],cnt,tim[maxn];
vector<int>e[maxn],g[maxn];
stack<int>s;
void tarjan(int u){
low[u] = dfn[u] = ++id;
s.push(u);
for(auto v:e[u]){
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u],low[v]);
}else if(!color[v]){
low[u] = min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
cnt++;
while(1){
int x = s.top();s.pop();
color[x] = cnt;
if(x==u)break;
}
}
}
int main(){
IO;
int n,m,s;cin>>n>>m>>s;
forn(i,m){
int u,v;cin>>u>>v;
e[u].push_back(v);
}
tarjan(s);
for1(i,n)if(!dfn[i]) tarjan(i);
s = color[s];
for1(i,n)if(!e[i].empty()){
int u = color[i];
for(auto x:e[i]){
int v = color[x];
if(u==v)continue;
g[u].push_back(v);
tim[v]++;
}
}
int ans = 0;
for1(i,cnt)if(!tim[i]&&i!=s) ans++;
cout << ans <<'
';
return 0;
}
F.
題意:n500個人,要從nk張權值範圍(1-1e5)的牌中抽取k10張,每個人有自己喜愛的牌fi,如果手中有x張自己喜愛的牌那麽他的貢獻就爲hx。問所有人貢獻最大值多少。
思路:預處理dp,因爲每個人貢獻只跟自己喜愛的牌有關,所以可以貪心,但是問題在於有幾個人遇到了相同的牌,比如h0-4為1 2 3 10000,現在兩個人都喜歡一張牌,那麽40分其實貢獻最高。
所以dp預處理dpij
i為i個人重複,j為nm個物品
代碼:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int maxn = 1e5+5;
int num[maxn],f[maxn],h[11],dp[505][5500];
int main(){
IO;
int n,k;cin>>n>>k;
forn(i,n*k){
int x;cin>>x;
num[x]++;
}
forn(i,n){
int x;cin>>x;
f[x]++;
}
for1(i,k){
cin>>h[i];
}
forn(i,n){
forn(j,n*k){
for1(z,k){
dp[i+1][j+z] = max(dp[i+1][j+z],dp[i][j]+h[z]);
}
}
}
ll ans = 0;
for1(i,maxn)if(f[i]){
ans+=dp[f[i]][num[i]];
}
cout << ans <<'
';
return 0;
}