中国大学生程序设计竞赛(秦皇岛)正式赛东北大学秦皇岛分校(SMU Autumn 2024 Team Round 1)
中国大学生程序设计竞赛(秦皇岛)正式赛东北大学秦皇岛分校(SMU Autumn 2024 Team Round 1)
Problem A. 贵校是构造王国吗 I
思路
官方题解很清晰明了。
代码
#include <bits/stdc++.h> using namespace std; #define int long long #define endl '\n' #define PII pair<int,int> const int N=1e6+3; void solve() { int n,k; cin>>n>>k; int dq=1; vector<PII>ans; set<PII>st; ans.push_back({1,1}); st.insert({1,1}); dq++; int ls=1; for (int i = 2; i <=n ; ++i) { ans.push_back({i,ls}); st.insert({i,ls}); dq++; ls++; ans.push_back({i,ls}); st.insert({i,ls}); dq++; } ans.push_back({1,n}); st.insert({1,n}); dq++; if(dq>k){ for(auto [x,y]:ans){ cout<<x<<' '<<y<<endl; } return ; } else{ for (int i = 1; i <=n ; ++i) { for (int j = 1; j <=n ; ++j) { if(st.count({i,j})==0){ ans.push_back({i,j}); if(ans.size()==k){ for(auto [x,y]:ans){ cout<<x<<' '<<y<<endl; } return ; } } } } } } signed main() { ios::sync_with_stdio(false),cin.tie(0); int t=1; // cin>>t; while(t--){ solve(); } return 0; }
Problem D. 茶和咖啡
思路
和题解类似。不过我们是用线段树维护前缀最小的物品。
代码
#include<bits/stdc++.h> using namespace std; #define int long long #define PII pair<int,int> #define INF INT_MAX #define N 200010 #define lc p<<1 #define rc p<<1|1 int n, w[N]; int a[N],b[N]; struct node{ int l,r; PII mi; }tr[N<<2],tr1[N<<2]; void push_up(int p){ tr[p].mi=min(tr[lc].mi,tr[rc].mi); } void build(int p,int l,int r){ tr[p]={l,r,{0,0}}; if(l==r){tr[p]={l,r,{w[l]-b[l],l}};return;} int mid=(l+r)>>1; build(lc,l,mid); build(rc,mid+1,r); push_up(p); } void update(int p,int x,int k){ if(tr[p].l==x and tr[p].r==x){ tr[p].mi.first+=k; return; } int mid=tr[p].l+tr[p].r>>1; if(x<=mid)update(lc,x,k); if(x>mid)update(rc,x,k); push_up(p); } PII query(int p,int x,int y){ if(x<=tr[p].l and tr[p].r<=y){ return tr[p].mi; } int mid=tr[p].l+tr[p].r>>1; PII sum={INF,0}; if(x<=mid){ sum=min(sum, query(lc,x,y)); } if(y>mid){ sum=min( query(rc,x,y),sum); } return sum; } void push_up1(int p){ tr1[p].mi=min(tr1[lc].mi,tr1[rc].mi); } void build1(int p,int l,int r){ tr1[p]={l,r,{0,0}}; if(l==r){tr1[p]={l,r,{w[l]-b[l],l}};return;} int mid=(l+r)>>1; build1(lc,l,mid); build1(rc,mid+1,r); push_up1(p); } void update1(int p,int x,int k){ if(tr1[p].l==x and tr1[p].r==x){ tr1[p].mi.first+=k; return; } int mid=tr1[p].l+tr1[p].r>>1; if(x<=mid)update1(lc,x,k); if(x>mid)update1(rc,x,k); push_up1(p); } PII query1(int p,int x,int y){ if(y==0)return {INF,0}; if(x<=tr1[p].l and tr1[p].r<=y){ return tr1[p].mi; } int mid=tr1[p].l+tr1[p].r>>1; PII sum={INT_MAX,0}; if(x<=mid){ sum=min(sum, query1(lc,x,y)); } if(y>mid){ sum=min( query1(rc,x,y),sum); } return sum; } void solve(){ int q; cin>>n>>q; for (int i = 1; i <=n ; ++i) { cin>>w[i]; a[i]=b[i]=0; } build(1,1,n); for(int i=1;i<=q;i++){ int x,y; cin>>x>>y; a[x]+=y; } b[n+1]=0; for(int i=n;i>=1;i--){ b[i]=a[i]+b[i+1]; } build1(1,1,n); int pos=n,s=0; int ans=0; for(int i=1;i<=n;i++){ auto[mn,pp]=query1(1,1,pos); mn+=s; if(pos<n){ auto[mn1,pp1]=query(1,pos+1,n); if(mn1<mn){ mn=mn1; pp=pp1; } } if(pp<=pos){ pos=pp-1; s=b[pp]; } update(1,pp,INF); update1(1,pp,INF); ans+=mn; cout<<ans<<' '; }cout<<endl; } signed main(){ ios::sync_with_stdio(false); cin.tie(0); int T=1; cin>>T; while(T--){ solve(); } return 0; }
Problem G. 最大路径
思路
懒得写了,题解写得很清楚,赞
代码
#include <bits/stdc++.h> using namespace std; #define int long long #define endl '\n' #define PII pair<int,int> const int N=1e6+3; void solve() { int n,m; cin>>n>>m; int ans=0; vector<int>a(n),b(m); for (int i = 0; i <n ; ++i) { cin>>a[i]; } for (int i = 0; i <m ; ++i) { cin>>b[i]; } for (int i = 1; i <n ; ++i) { ans+=abs(a[i-1]-a[i]); } for (int i = 1; i <m ; ++i) { ans+=abs(b[i-1]-b[i]); } cout<<ans<<endl; } signed main() { ios::sync_with_stdio(false),cin.tie(0); int t=1; // cin>>t; while(t--){ solve(); } return 0; }
Problem J. 维克多词典
思路
子集 DP。
单词长度很小,可以考虑状压DP求答案。
设 \(dp_S\) 为为学习完 S 的集合长度的单词的最小天数,转移的时候枚举每个 S 的子集即可。
代码
#include <bits/stdc++.h> using namespace std; typedef long long int ll; #define int long long #define double long double #define LL __int128 #define PII pair<double,double> #define PIC pair<int,char> #define endl '\n' typedef long long ll; const int N = 1e4 + 10; int a[100]; vector<int>q; PII S[N]; vector<int>g[20]; void solve() { int n, w; cin >> n >> w; int t = 0; for (int i = 1; i <= n; i++) { int x; cin >> x; if (!a[x]) { t++; q.push_back(x); } a[x]++; } for(int i=0;i<(1<<t);i++){ S[i]={1e9,1e9}; g[__builtin_popcount(i)].push_back(i); } S[0]={0,0}; for (int i = 0; i < t; ++i){ for(auto j:g[i]){ for(int k=0;k<t;k++){ if ((j >> k & 1)==0) { PII x=S[j]; if(a[q[k]]+x.second<=w){ x.second+=a[q[k]]; }else{ x.first++; x.second=a[q[k]]; } S[j^(1<<k)]=min(S[j^(1<<k)],x); } } } } cout<<S[(1<<t)-1].first+(S[(1<<t)-1].second>0)<<endl; } signed main() { ios::sync_with_stdio(false); cin.tie(0); int t = 1; // cin>>t; while (t--) { solve(); } return 0; }
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18450322
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
,
,
,
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步