这个比赛读题时间过长,做题时间比较少,一直在机械的打代码,没有做到后面值得思考的题目,有点可惜
A题 树链剖分维护到根节点的答案即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+10; int n,m; int h[N],ne[N],e[N],idx; int id[N],w[N],pre[N],top[N],times; int fa[N],sz[N],son[N],depth[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } struct node{ int l,r; ll sum; }tr[N]; void dfs(int u){ int i; sz[u]=1; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa[u]) continue; fa[j]=u; depth[j]=depth[u]+1; dfs(j); sz[u]+=sz[j]; if(sz[j]>sz[son[u]]){ son[u]=j; } } } void dfs1(int u,int x){ pre[u]=++times; id[times]=u; top[u]=x; if(!son[u]) return; dfs1(son[u],x); int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa[u]||j==son[u]) continue; dfs1(j,j); } } void build(int u,int l,int r){ if(l==r){ tr[u]={l,r,0}; } else{ tr[u]={l,r,0}; int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); } } void pushup(int u){ tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum; } void modify(int u,int l,int x){ if(tr[u].l==tr[u].r){ tr[u].sum+=x; return ; } int mid=tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,x); else modify(u<<1|1,l,x); pushup(u); } ll query(int u,int l,int r){ if(tr[u].l>=l&&tr[u].r<=r){ return tr[u].sum; } int mid=tr[u].l+tr[u].r>>1; ll res=0; if(l<=mid) res+=query(u<<1,l,r); if(r>mid) res+=query(u<<1|1,l,r); return res; } ll qpath(int x,int y){ ll res=0; while(top[x]!=top[y]){ if(depth[top[x]]<depth[top[y]]) swap(x,y); res=res+query(1,pre[top[x]],pre[x]); x=fa[top[x]]; } if(depth[x]>depth[y]) swap(x,y); res=res+query(1,pre[x],pre[y]); return res; } int main(){ ios::sync_with_stdio(false); cin>>n>>m; int i; memset(h,-1,sizeof h); int rt=0; for(i=1;i<=n;i++){ int x; cin>>x; if(x!=0){ add(i,x); add(x,i); } if(!x){ rt=i; } } depth[rt]=1; fa[rt]=0; dfs(rt); dfs1(rt,rt); build(1,1,n); while(m--){ int u,x,v; cin>>u>>x>>v; cout<<qpath(v,rt)<<endl; modify(1,pre[u],x); } }
B题 从前往后枚举,主要要和变成0的情况去min
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; int s[123456]; int s1[123456]; int cnt,tot; int main(){ int t; scanf("%d",&t); while(t--){ cnt=0; s1[0]=0; tot=1; string a,b; string c=""; cin>>a>>b; for(int i=0;i<(int)a.size();i++)c+="0"; int z=0; for(int i=0;i<(int)a.size();i++){ int aa=a[i]-'0',bb=b[i]-'0'; if((aa+z)%2!=bb){ s[cnt++]=i+1; z++; } } z=0; for(int i=0;i<(int)c.size();i++){ int aa=c[i]-'0',bb=b[i]-'0'; if((aa+z)%2!=bb){ s1[tot++]=i+1; z++; } } if(cnt<tot){ if(!cnt){ printf(" "); continue; } for(int i=0;i<cnt-1;i++) printf("%d ",s[i]); printf("%d",s[cnt-1]); printf(" "); } else{ for(int i=0;i<tot-1;i++) printf("%d ",s1[i]); printf("%d",s1[tot-1]); printf(" "); } } }
C题 模拟水题
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; int a[27]; struct node{ ll l,r; }s[N]; int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int n; cin>>n; ll ans=0; ll tmp=0; int i; for(i=1;i<=n;i++){ cin>>s[i].l>>s[i].r; } for(i=1;i<=n;i++){ if(tmp>=s[i].l&&tmp<=s[i].r){ ans++; } else{ if(s[i].r<tmp){ ans+=(tmp-s[i].r); tmp=s[i].r; ans++; } else{ ans+=(s[i].l-tmp); tmp=s[i].l; ans++; } } } cout<<ans<<endl; } }
D题 猜结论
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; int a[123456]; int s[123456]; int cnt; int main(){ int t; scanf("%d",&t); while(t--){ cnt=0; int n;scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); } sort(a,a+n); for(int i=0,j=0;i<n;i=j){ while(a[j]==a[i]&&j<n)j++; if((j-i)%2==1)s[cnt++]=a[i]; } if(!cnt){ cout<<a[0]<<endl; } else if(cnt==1){ cout<<-1<<endl; } else if(cnt==2){ cout<<s[0]<<endl; }else{ cout<<s[cnt-1]<<endl; } } }
E题
F题 输出答案
H题 线段树区间修改
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; struct node{ int l,r; int mx; int lazy; }tr[N<<2]; int a[N]; int n,m; void pushup(int u){ tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx); } void build(int u,int l,int r){ if(l==r){ tr[u]={l,r,a[l],-1}; } else{ tr[u]={l,r,0,-1}; int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); pushup(u); } } void pushdown(int u){ int x=tr[u].lazy; tr[u<<1].mx=tr[u<<1|1].mx=x; tr[u<<1].lazy=tr[u<<1|1].lazy=x; tr[u].lazy=-1; } void modify(int u,int l,int r,int x){ if(tr[u].l>=l&&tr[u].r<=r){ tr[u].mx=0; tr[u].lazy=x; return ; } if(tr[u].lazy!=-1) pushdown(u); int mid=tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,r,x); if(r>mid) modify(u<<1|1,l,r,x); pushup(u); } int main(){ //ios::sync_with_stdio(false); int t; cin>>t; while(t--){ scanf("%d%d",&n,&m); int i; for(i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); while(m--){ int l,r; scanf("%d%d",&l,&r); modify(1,l,r,0); printf("%d ",tr[1].mx); } } }
I题 祖冲之点集
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; int a[27]; int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); if(n<=2)printf("No "); else printf("Yes "); } }
J题 dfs染色
显然看出二分单调性,对于check函数,需要设计一下
我们通过反向考虑,对两个点边大于权值的建边,之后进行染色看是否存在冲突。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; const int inf=1e9+7; vector<pll> s[N]; vector<int> g[N]; int vis[N]; int n,m; int dfs(int u,int fa,int x){ int i; vis[u]=x; for(i=0;i<(int)g[u].size();i++){ int j=g[u][i]; if(j==fa) continue; if(vis[j]==vis[u]) return 0; if(vis[j]==(vis[u]^1)) continue; if(vis[j]==-1){ if(!dfs(j,u,!x)) return 0; } } return 1; } bool check(int d){ int i; for(i=0;i<=n;i++){ g[i].clear(); vis[i]=-1; } for(i=1;i<=n;i++){ for(auto x:s[i]){ if(x.second>d){ g[i].push_back(x.first); } } } int flag=1; for(i=1;i<=n;i++){ if(vis[i]==-1){ flag=dfs(i,-1,0); if(!flag){ return 0; } } } return 1; } int main(){ int t; ios::sync_with_stdio(false); cin>>t; while(t--){ cin>>n>>m; int i,j; for(i=0;i<=n;i++) s[i].clear(); for(i=1;i<=m;i++){ int a,b,c; cin>>a>>b>>c; s[a].push_back({b,c}); s[b].push_back({a,c}); } int l=0,r=inf; while(l<r){ int mid=l+r>>1; if(check(mid)){ r=mid; } else{ l=mid+1; } } cout<<l<<endl; } return 0; }
K1题 模拟
#include<cstdio> #include<iostream> #include<string> using namespace std; int a[13]= {0,31,0,31,30,31,30,31,31,30,31,30,31}; bool check(int n) { if(n%400==0||(n%4==0&&n%100!=0)) return true; return false; } int main() { string s; while(getline(cin,s)&&s[0]!='#') { int ans=0; int i=0; while((i+7)<(int)s.length()) { for(;s[i+7]!=' '&&(i+7)<(int)s.length(); i++) { if(s[i]==s[i+7]&&s[i+1]==s[i+6]&&s[i+2]==s[i+5]&&s[i+3]==s[i+4]) { int y,m,d; d=(s[i+7]-'0')+(s[i+6]-'0')*10; m=(s[i+5]-'0')+(s[i+4]-'0')*10; y=(s[i+3]-'0')+(s[i+2]-'0')*10+(s[i+1]-'0')*100+(s[i]-'0')*1000; if(check(y)) a[2]=29; else a[2]=28; if(y>0&&m>0&&d>0&&m<=12&&d<=a[m]) ans++; } } if(s[i+7]==' ') i=i+7; while(s[i]==' ') i++; } printf("%d ",ans); } return 0; }