写题一定要自己独立思考去写,如果当场做不出来,那么结束后一定要自己再手写,不可直接复制粘贴,自己独立去写才会发现问题
1后无0,0前无1,前缀和贪心 On优化On^2查找
怪怪的,数组范围2e5开到1e6加了memset才能过全部数据
const int N =1e6+10;
char a[N];
int b[N], c[N];
void solved()
{
cin>>a+1;int n=strlen(a+1);
memset(b,0,sizeof b);
memset(c,0,sizeof c);
for (int i = n - 1; i >= 1; i--)
{
if (a[i + 1]=='b')
b[i] += b[i + 1] + 1;
else
b[i] += b[i + 1];
}
for (int i = 2; i <= n; i++)
{
if (a[i - 1]=='a')
c[i] += c[i - 1] + 1;
else
c[i] += c[i - 1];
}
int mx = 2e9;
for (int i = 1; i <= n; i++)
{
mx = min(b[i] + c[i], mx);
}
printf("%d\n",mx);
}
dfs数一维数组连续1的个数
通过判断最后一位就好了
void dfs(int pos,int ans)
{
if(pos>33){res=ans;return ;}
if(q[pos]!=1&&q[pos-1]==1)dfs(pos+1,ans+1);
if(res!=-1)return;
dfs(pos+1,ans);
if(res!=-1)return;
}
void solved()
{
memset(q,0,sizeof q);
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>q[i];
res=-1;
int ans=0;
//for(int i=1;i<=n+5;i++)if(q[i]!=1&&q[i-1]==1)ans++;
dfs(1,0);
printf("%d\n",res);
;
}
图论的dfs,void递归数组存答案
简单树的遍历,遇头节点直接过,不然更新当前答案
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
ll cnt[N],dis[N];
int w[N],c[N];
int h[N],ne[N<<1],e[N<<1],idx;
int n;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa,ll sum){
dis[u]=sum;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa)continue;
ll t=cnt[c[j]];
if(t>w[j])dfs(j,u,sum);
else {
cnt[c[j]]=w[j];
dfs(j,u,sum-t+w[j]);
cnt[c[j]]=t;
}
}
}
int main(){
memset(h,-1, sizeof h);
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=1;i<=n;i++)cin>>c[i];
for(int i=1;i<n;i++){
int x,y;cin>>x>>y;
add(x,y);
add(y,x);
}
cnt[c[1]]=w[1];
dfs(1,0,w[1]);
for(int i=1;i<=n;i++) cout<<dis[i]<<endl;
return 0;
}
传送门
acwing上:起点不定,范围在0到正无穷,给出一个传送求最短路,直接枚举左进传送门,右进传送门,跳过传送门取最小值
int main()
{
cin>>a>>b>>x>>y;
d1=abs(b-a);
d2=abs(a-x)+abs(b-y);
d3=abs(a-y)+abs(b-x);
printf("%d",min({d1,d2,d3}));
return 0;
}
牛客上:起点为0,不能跳过传送门,问是否会撞墙,直接存路径,直接从前往后走模拟,遇传送门则传送,否则++直走,看是否会碰壁
bool st[N];
unordered_map<int,int> mp;
void solved()
{
int n,m,q;
cin>>n>>m>>q;
for(int i=0;i<m;i++)
{
int l,r;cin>>l>>r;
mp[l]=r,mp[r]=l;
}
for(int i=0;i<q;i++)
{
int x;cin>>x;st[x]=1;
}
for(int pos=1;pos<=n;pos++)
{
if(mp[pos])pos=mp[pos];
if(st[pos]){
puts("NO");return;
}
}
puts("YES");
;
}
翻牌
n张牌背面朝上,每次最多翻m张
一直WA,发现是没有考虑边界,m==0且n==0有解0,只m==0是无法翻牌无解
所以!!!一定要考虑同时为0,1,或者某种情况,简单题一般就是看这些细节
STL使用
竞赛比时间的话,边读入边操作更快
这里就可以边读入,边存map
void solved()
{
int m,n;cin>>m>>n;
if(m==0&&n==0)puts("0");
else if(!n)puts("-1");
else {
int ans=m/n;
if(m/n!=(double)m/n)ans++;
printf("%d\n",ans);
}
;
}
substr
substr(i,n); i为string中的起点,n为截取长度
void solved()
{
while(cin>>n)
{
int ans=0;
string s;cin>>s;
for(int i=0;i<n-3;i++)
{
if(s.substr(i,4)=="2020")ans++,i+=3;
}
print(ans);puts("");
}
;
}
思维
如果满足序列为奇数,那么两两必有偶,即>=3无解
void solved()
{
while(cin>>n>>m)
{
memset(g,0,sizeof g);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>g[i][j];
if(n==1)puts("Yes");
else if(n>2)puts("No");
else {
int x=0;
for(int i=0,j=0;i<m;i++)
x+=abs(g[j][i]-g[j+1][i]);
puts(x&1?"Yes":"No");
}
}
;
}
判断大图里找字符串
找合适的子性质就好,这里是找2018中8的T
void solved()
{
while(cin>>n>>m)
{
memset(g,0,sizeof g);
for(int i=0;i<n;i++)cin>>g[i];
bool ok=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
{
if(g[i][j]=='o'&&g[i-1][j]=='o'&&g[i+1][j]=='o'&&g[i][j+1]=='o')
ok=1;
if(ok)break;
}
if(ok)break;
}
puts(ok?"2018":"2020");
}
;
}
dfs按照性质搜索
大致题意,k次操作,每次只能走到边界或者撞上车子、障碍才停下
和扫对角线类似,xx,yy初始化i,j
while递归check性质
因为是dfs找答案所以回溯时要恢复现场
int m,n,k;
char g[N][N];
int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
bool check(int x,int y)
{
if(x<0||x>=n||y<0||y>=m||g[x][y]=='R'||g[x][y]=='X')return 0;
return 1;
}
bool ok=0;
void dfs(int u)
{
if(ok)return;
if(u>k)return;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(g[i][j]=='R')
{
for(int p=0;p<4;p++)
{
int xx=i,yy=j;
while(check(xx+dx[p],yy+dy[p]))xx+=dx[p],yy+=dy[p];
if(g[xx][yy]=='D')ok=1;
if(ok)return;
swap(g[i][j],g[xx][yy]);
dfs(u+1);
swap(g[i][j],g[xx][yy]);
}
}
}
}
void solved()
{
cin>>m>>n>>k;
for(int i=0;i<n;i++)cin>>g[i];
ok=0;
dfs(1);
puts(ok?"YES":"NO");
;
}
暴搜dfs
直接暴力递归,每次递归完自动往下走,不考虑时间成本,注意剪枝。。
double get(double a,double b,double c)
{
double p=(a+b+c)/2.0;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
bool check(int a,int b,int c)
{
if(a+b>c&&a+c>b&&b+c>a)return 1;
return 0;
}
int n;
double res=-1;
void dfs(int cnt,int a,int b,int c){
if(cnt>n) return;
if(check(a,b,c)){
double sum=get(a,b,c);
if(res<sum) res=sum;
}
dfs(cnt+1,a,b,c+q[cnt]);
dfs(cnt+1,a+q[cnt],b,c);
dfs(cnt+1,a,b+q[cnt],c);
dfs(cnt+1,a,b,c);
}