这场打的顺手到不敢相信。如果不是vp的话估计肯定打不到这个成绩。
A:最大显然,最小的话每次暴力给最小的+1。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 110 int n,m,a[N],mx,s; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(),s=max(s,a[i]); s+=m; for (int i=1;i<=m;i++) { int mx=1; for (int j=2;j<=n;j++) if (a[j]<a[mx]) mx=j; a[mx]++; } int mx=1;for (int i=1;i<=n;i++) mx=max(mx,a[i]); cout<<mx<<' '<<s; return 0; }
B:每种蔬菜集合取最小值,枚举选哪些即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 1010 int n,ans=700000000,f[8]; struct data{int x,y; }a[N]; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read();for (int i=1;i<8;i++) f[i]=ans; for (int i=1;i<=n;i++) { a[i].x=read(); char c=getchar(); while (c<'A'||c>'Z') c=getchar(); while (c>='A'&&c<='Z') { a[i].y+=1<<c-'A'; c=getchar(); } f[a[i].y]=min(f[a[i].y],a[i].x); } for (int i=0;i<8;i++) for (int j=0;j<8;j++) for (int k=0;k<8;k++) if ((i|j|k)==7) ans=min(ans,f[i]+f[j]+f[k]); if (ans==700000000) cout<<-1; else cout<<ans; return 0; }
C:显然就是取一些数使乘积最大。讨论一下各种情况。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 200010 int n,a[N]; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(); int cnt=0; for (int i=1;i<=n;i++) { a[i]=read(); cnt+=a[i]<0; } int last=0; if (cnt%2==0) { int cnt=0; for (int i=1;i<=n;i++) if (a[i]==0) { cnt++; if (last) printf("%d %d %d\n",1,last,i); last=i; } if (last&&cnt<n) printf("%d %d\n",2,last); last=0; for (int i=1;i<=n;i++) if (a[i]!=0) { if (last) printf("%d %d %d\n",1,last,i); last=i; } } else { int mx=0,cnt=0; for (int i=1;i<=n;i++) if (a[i]<0&&(!mx||a[i]>a[mx])) mx=i; for (int i=1;i<=n;i++) if (a[i]==0) cnt++,printf("%d %d %d\n",1,i,mx); if (cnt<n-1) printf("%d %d\n",2,mx); last=0; for (int i=1;i<=n;i++) if (a[i]!=0&&i!=mx) { if (last) printf("%d %d %d\n",1,last,i); last=i; } } return 0; }
D:前缀和后即每次询问有多少个数与x的和小于y。随便拿个数据结构维护一下,感觉treap比较方便。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 200010 #define ll long long #define lson tree[k].ch[0] #define rson tree[k].ch[1] int n,root,cnt=0; ll m,a[N],ans; struct data{ll x;int p,ch[2],s; }tree[N]; void up(int k){tree[k].s=tree[lson].s+tree[rson].s+1;} void move(int &k,int p) { int t=tree[k].ch[p]; tree[k].ch[p]=tree[t].ch[!p],tree[t].ch[!p]=k,up(k),up(t),k=t; } void ins(int &k,ll x) { if (k==0){k=++cnt;tree[k].x=x,tree[k].s=1,tree[k].p=rand();tree[k].ch[0]=tree[k].ch[1]=0;return;} tree[k].s++; if (x<tree[k].x) {ins(lson,x);if (tree[lson].p>tree[k].p) move(k,0);} else {ins(rson,x);if (tree[rson].p>tree[k].p) move(k,1);} } ll query(int k,ll s) { if (k==0) return 0; if (tree[k].x>s) return query(lson,s); else return query(rson,s)+tree[lson].s+1; } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif cin>>n>>m;m--; srand(20020509); for (int i=1;i<=n;i++) a[i]=a[i-1]+read(); ins(root,0); for (int i=1;i<=n;i++) { ans+=i-query(root,a[i]-m-1); ins(root,a[i]); } cout<<ans; return 0; }
E:从小到大倒退期望即可。每次需要知道某格子到其他小于他的格子的距离平方之和,显然横纵坐标可以分别计算,然后展开即可维护。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 1010 #define P 998244353 int n,m,s,sum,Sum[2],Sqr[2],Cnt[2]; int ksm(int a,int k) { int s=1; for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P; return s; } int trans(int x,int y){return (x-1)*m+y;} struct data{int x,y,v,ans; }a[N*N]; bool cmp(const data&a,const data&b) { return a.v<b.v; } void update(int k,int x,int p) { a[k].ans=(a[k].ans+1ll*x*x%P*Cnt[p]%P+Sqr[p]-2ll*x*Sum[p]%P+P)%P; } void ins(int x,int p) { Cnt[p]++;Sum[p]=(Sum[p]+x)%P;Sqr[p]=(Sqr[p]+1ll*x*x%P)%P; } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(),m=read(); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) a[trans(i,j)].x=i,a[trans(i,j)].y=j,a[trans(i,j)].v=read(); int x=read(),y=read();s=trans(x,y); sort(a+1,a+n*m+1,cmp); for (int i=1;i<=n*m;i++) { int t=i; while (t<n*m&&a[t+1].v==a[i].v) t++; for (int j=i;j<=t;j++) { a[j].ans=sum; update(j,a[j].x,0),update(j,a[j].y,1); a[j].ans=1ll*a[j].ans*ksm(i-1,P-2)%P; } for (int j=i;j<=t;j++) { ins(a[j].x,0),ins(a[j].y,1); sum=(sum+a[j].ans)%P; } i=t; } for (int i=1;i<=n*m;i++) if (trans(a[i].x,a[i].y)==s) {cout<<a[i].ans;return 0;} }
F:想了半天觉得一点也不可做,于是大力贪心,莫名其妙就过了。设f[i]为i子树内划分集合的最少数量,g[i]为i子树中这些集合的最大深度的最小值。dp时贪心地合并各子树内最大深度最小的那些集合,即把小的合并在一块,大的不管了。并没有想清楚为什么对。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 1000010 int n,m,p[N],degree[N],deep[N],fa[N],f[N],g[N],b[N],root,t=0; struct data{int to,nxt; }edge[N<<1]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} void dp(int k) { bool flag=1; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]) flag=0,dp(edge[i].to); if (flag) f[k]=1,g[k]=0; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]) f[k]+=f[edge[i].to]; int cnt=0; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]) b[++cnt]=g[edge[i].to]+1; sort(b+1,b+cnt+1); if (cnt) g[k]=b[1]; for (int i=1;i<cnt;i++) if (b[i]+b[i+1]<=m) f[k]--,g[k]=b[i+1]; } void dfs(int k) { for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]) { fa[edge[i].to]=k; deep[edge[i].to]=deep[k]+1; dfs(edge[i].to); } } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(),m=read(); for (int i=1;i<n;i++) { int x=read(),y=read(); addedge(x,y),addedge(y,x); degree[x]++,degree[y]++; } for (int i=1;i<=n;i++) if (degree[i]>1) {root=i;break;} dfs(root); dp(root); cout<<f[root]; return 0; }
result:rank 5