A
不解释
#include<bits/stdc++.h> using namespace std; namespace red{ inline int read() { int x=0;char ch,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=0,ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } int a[5]; inline bool check(int id) { return (a[id]+a[id+1]>a[id+2]&&a[id+2]-a[id+1]<a[id]); } inline bool check2(int id) { return (a[id]+a[id+1]>=a[id+2]); } inline void main() { for(int i=1;i<=4;++i) a[i]=read(); sort(a+1,a+4+1); if(check(1)||check(2)) puts("TRIANGLE"); else if(check2(1)||check2(2)) puts("SEGMENT"); else puts("IMPOSSIBLE"); } } signed main() { red::main(); return 0; }
B
找到位置开始\(dfs\)
#include<bits/stdc++.h> using namespace std; namespace red{ inline int read() { int x=0;char ch,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=0,ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } int n,m,sum; char ch; char mp[110][110]; bool vis[1010]; bool g[110][110]; int dx[]={0,-1,1,0,0},dy[]={0,0,0,1,-1}; inline void dfs(int x,int y) { for(int i=1;i<=4;++i) { int tx=x+dx[i],ty=y+dy[i]; if(tx<1||tx>n||ty<1||ty>m) continue; if(g[tx][ty]) continue; g[tx][ty]=1; if(mp[tx][ty]==ch) dfs(tx,ty); else if(mp[tx][ty]!='.'&&!vis[mp[tx][ty]]) { vis[mp[tx][ty]]=1; ++sum; } } } inline void main() { n=read(),m=read(); for(ch=getchar();(ch<'A'||ch>'Z');ch=getchar()); for(int i=1;i<=n;++i) { scanf("%s",mp[i]+1); } for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) { if(mp[i][j]==ch) { dfs(i,j); printf("%d\n",sum); return; } } } } } signed main() { red::main(); return 0; }
C
也就一个模拟,前后维护两个指针
#include<bits/stdc++.h> using namespace std; namespace red{ inline int read() { int x=0;char ch,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=0,ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } const int N=1e5+10; int n; int a[N]; int t1,t2,sum1,sum2; inline void main() { n=read(); for(int i=1;i<=n;++i) { a[i]=read(); } t1=0,t2=n+1; while(t1<t2-1) { ++t1; sum1+=a[t1]; while(sum2<sum1&&t1<t2-1) --t2,sum2+=a[t2]; } cout<<t1<<' '<<n-t1<<endl; } } signed main() { red::main(); return 0; }
D
看了眼数据范围:
\(3\le n\le 10\) , \(1\le b < a\le 10\) , \(1\le h_i \le 15\)
\(!\)
搜他丫的
注意两边是没法点火球的,先把两边消掉,然后在中间迭代加深
因为\(n=3\)的时候预处理两边会出锅,先判掉
然后提交
\(TLE\)
发现一个性质:火球先后顺序无关
减少一下搜索重复状态:只在一个火球之后扔火球
\(AC\)了
#include<bits/stdc++.h> using namespace std; namespace red{ inline int read() { int x=0;char ch,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=0,ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } const int N=110; int n,a,b; int hp[N]; int bp[N],c[N]; int d[N],ans[N]; int t,sum; inline bool dfs(int pre,int now,int up) { if(now>up) { for(int i=1;i<=t;++i) if(~bp[i]) return 0; return 1; } for(int i=pre;i<=t;++i) { int q1=bp[i-1],q2=bp[i],q3=bp[i+1]; bp[i-1]=max(bp[i-1]-b,-1); bp[i]=max(bp[i]-a,-1); bp[i+1]=max(bp[i+1]-b,-1); ans[now]=c[i]; if(dfs(i,now+1,up)) return 1; bp[i-1]=q1,bp[i]=q2,bp[i+1]=q3; } return 0; } inline void solve() { sum=max(max(hp[1]/b+1,hp[3]/b+1),hp[2]/a+1); printf("%d\n",sum); for(int i=1;i<=sum;++i) printf("%d ",2); exit(0); } inline void main() { n=read(),a=read(),b=read(); for(int i=1;i<=n;++i) hp[i]=read(); if(n==3) solve(); t=(hp[1])/b+1; hp[1]=-1; hp[2]=max(hp[2]-t*a,-1); hp[3]=max(hp[3]-t*b,-1); for(int i=1;i<=t;++i) d[i]=2; sum+=t; t=(hp[n])/b+1; hp[n]=-1; hp[n-1]=max(hp[n-1]-t*a,-1); hp[n-2]=max(hp[n-2]-t*b,-1); for(int i=sum+1;i<=sum+t;++i) d[i]=n-1; sum+=t; bool flag=0; for(int i=1;i<=n;++i) if(~hp[i]) flag=1; if(!flag) { printf("%d\n",sum); for(int i=1;i<=sum;++i) printf("%d ",d[i]); return; } for(int i=1;;++i) { t=0; for(int j=2;j<n;++j) bp[++t]=hp[j],c[t]=j; if(dfs(1,1,i)) { for(int j=sum+1;j<=sum+i;++j) d[j]=ans[j-sum]; sum+=i; sort(d+1,d+sum+1); printf("%d\n",sum); for(int j=1;j<=sum;++j) printf("%d ",d[j]); return; } } } } signed main() { red::main(); return 0; }
然后发现这题目是可以\(dp\)的……
设\(dp[i][j][k]\)表示前\(i\)个都死了,第\(i\)个用了\(j\)个火球,第\(i+1\)个用了\(k\)个火球的最小代价
不得不说这个状态很巧妙……
然后暴力转移\(n*h^3\),其中\(h=max\{h_i\}\)
其中我们发现当枚举了当前状态之后,之前那个转移状态可以后缀最大值优化,优化到\(n*h^2\)
#include<bits/stdc++.h> using namespace std; namespace red{ inline int read() { int x=0;char ch,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=0,ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } const int N=110; int n,a,b,ret,t0,t1,t2; int hp[N]; int f[21][21][21],g[21][21][21]; inline void main() { n=read(),a=read(),b=read(); for(int i=1;i<=n;++i) hp[i]=read(); memset(f,0x3f,sizeof(f)); for(int i=1;i<=20;++i) if(i*b>hp[1]) f[1][0][i]=0; //kcz:i-n死完了,i-1用j个,i用k个 //俺:1-i死完了,i用j个,i用k+1个 //dp方法:直接dp,最后输出满足要求的状态 for(int i=1;i<=n;++i) { if(i>1) { for(int k=0;k<=16;++k) { int tmp=hp[i]-k*b; for(int j=0;j<=16;++j) { f[i][j][k]=j+g[i-1][tmp<0?0:tmp/b+1][j]; tmp-=a; } } } for(int k=0;k<=16;++k) { g[i][16][k]=f[i][16][k]; for(int j=15;~j;--j) g[i][j][k]=min(g[i][j+1][k],f[i][j][k]); } } int i=n,j=0,k=0; printf("%d\n",f[i][j][k]); while(--i>1) { int tmp=hp[i+1]-j*a-k*b; int l=tmp<0?0:tmp/b+1; while(f[i][l][j]!=f[i+1][j][k]-j) ++l; k=j,j=l; for(int u=1;u<=l;++u) printf("%d ",i); } } } signed main() { red::main(); return 0; } /* 9 3 1 1 5 2 4 6 2 3 4 2 */
E
预处理\(st\)表
二分求答案
然后统计答案
#include<bits/stdc++.h> using namespace std; namespace red{ inline int read() { int x=0;char ch,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=0,ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } const int N=1e5+10; int n,m,l,r,mid,ret,sum; int a[N],lg[N]; bool s[N]; int f[N][21],g[N][21]; inline int get_max(int l,int r) { int k=lg[r-l+1]-1; return max(f[l][k],f[r-(1<<k)+1][k]); } inline int get_min(int l,int r) { int k=lg[r-l+1]-1; return min(g[l][k],g[r-(1<<k)+1][k]); } inline bool check(int x) { for(int l=1;l<=n;++l) { int r=l+x-1; if(r>n) return 0; if(get_max(l,r)-get_min(l,r)<=m) return 1; } return 0; } inline void get_sum(int x) { for(int l=1;l<=n;++l) { int r=l+x-1; if(r>n) return; if(get_max(l,r)-get_min(l,r)<=m) ++sum,s[l]=1; } } inline void main() { n=read(),m=read(); for(int i=1;i<=n;++i) a[i]=f[i][0]=g[i][0]=read(); for(int i=1;i<=n;++i) lg[i]=lg[i>>1]+1; lg[0]=1; for(int i=1;i<=20;++i) { for(int j=1;j+(1<<i)-1<=n;++j) { f[j][i]=max(f[j][i-1],f[j+(1<<(i-1))][i-1]); g[j][i]=min(g[j][i-1],g[j+(1<<(i-1))][i-1]); } } l=1,r=n; while(l<=r) { mid=(l+r)>>1; if(check(mid)) ret=mid,l=mid+1; else r=mid-1; } get_sum(ret); printf("%d %d\n",ret,sum); for(int i=1;i<=n;++i) { if(s[i]) printf("%d %d\n",i,i+ret-1); } } } signed main() { red::main(); return 0; }
来源:https://www.cnblogs.com/knife-rose/p/12250216.html