10/10
Posted lin1874
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10/10相关的知识,希望对你有一定的参考价值。
A:
题意:给一个大小为n的数组A,让你把A分成若干个(1 or more)新的数组,使得新数组的和不为0;
解:NO的情况只有 数组内所有元素都为0
YES的情况:1.数组A的所有元素和不为0:直接输出(1,n);
2.数组A的所有元素和为0:必定存在sum(1,i)!=0,sum(i+1,n)!=0;//(sum(1,i)表示元素下标和(1-i))
#include <bits/stdc++.h> using namespace std; const int MAXN=1e5+10; int a[MAXN]; int main(){ int n; cin>>n; int sum=0; for(int i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; } if(sum){ cout<<"YES"<<endl; cout<<1<<endl; cout<<1<<‘ ‘<<n<<endl; } else{ int flag=0; for(int i=1;i<=n;i++){ sum+=a[i]; if(sum){ flag=1; cout<<"YES"<<endl; cout<<2<<endl; cout<<1<<‘ ‘<<i<<endl; cout<<i+1<<‘ ‘<<n<<endl; break; } } if(!flag)cout<<"NO"<<endl; } return 0; }
B:
题意:4*4的棋盘,是否存在放一个棋‘x‘,使得存在三个连续的‘x‘,(横竖斜)
解:暴力每个可能的位置,只有4*4;
#include <bits/stdc++.h> using namespace std; const int MAXN=1e5+10; char s[10][10]; int a[10][10]; int main(){ for(int i=1;i<=4;i++){ scanf("%s",s[i]+1); } for(int i=1;i<=4;i++){ for(int j=1;j<=4;j++){ if(s[i][j]==‘x‘){ a[i][j]=1; } else if(s[i][j]==‘o‘){ a[i][j]=-1; } else a[i][j]=0; } } int flag=0; for(int i=1;i<=4;i++){ for(int j=1;j<=2;j++){ if(a[i][j]+a[i][j+1]+a[i][j+2]>=2){ flag=1; } if(a[j][i]+a[j+1][i]+a[j+2][i]>=2){ flag=1; } } } for(int i=1;i<=4;i++){ for(int j=1;j<=4;j++){ if(i<=2&&j<=2){ if(a[i][j]+a[i+1][j+1]+a[i+2][j+2]>=2){ flag=1; } } else if(i<=2&&j>2){ if(a[i][j]+a[i+1][j-1]+a[i+2][j-2]>=2){ flag=1; } } } } if(flag)cout<<"YES"<<endl; else cout<<"NO"<<endl; return 0; }
C:
题意:给一个n的数组A,从数组A中找出一个可重复集合,集合满足所有元素的gcd不为1,输出最大 集合的个数
解:统计因子,将所有元素的因子进行统计,答案就是所有因子最大的个数,因为si<=1e5,因子也不会太大;
#include <bits/stdc++.h> using namespace std; const int MAXN=1e5+10; int num[MAXN]; int a[MAXN]; void gao(int x){ for(int i=2;i<=sqrt(x);i++){ if(x%i==0){ if(i*i!=x){ num[i]++;num[x/i]++; } else num[i]++; } } num[x]++; } int main(){ ios::sync_with_stdio(false); int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; gao(a[i]); } int ans=1; for(int i=2;i<=MAXN-5;i++){ ans=max(ans,num[i]); } cout<<ans<<endl; return 0; }
D:
题意:给一个字符串,‘!‘可以换为其他字母,满足整个字符串自循环,按题目顺序输出‘!‘换为其他字母的个数
解:模拟~用map瞎模拟过去;
#include <bits/stdc++.h> using namespace std; const int MAXN=1e5+10; char s[MAXN]; int a[5]; int num[5]; bool vis[5]; map<char,int>mp; int main(){ ios::sync_with_stdio(false); mp[‘R‘]=1;mp[‘B‘]=2;mp[‘Y‘]=3;mp[‘G‘]=4;mp[‘!‘]=0; scanf("%s",s); for(int i=0;i<strlen(s);i++){ if(s[i]!=‘!‘) a[i%4]=mp[s[i]]; else num[i%4]++; } for(int i=0;i<4;i++){ vis[a[i]]=true; } for(int i=0;i<4;i++){ if(a[i]==0){ for(int j=1;j<=4;j++){ if(!vis[j]){ a[i]=j; vis[j]=true; break; } } } } for(int i=1;i<=4;i++){ for(int j=0;j<4;j++){ if(a[j]==i){ cout<<num[j]<<‘ ‘; } } } cout<<endl; return 0; }
E:
解:线段树,字母用二进制存,每个结点存两个子节点的或值;
最后查询的时候二进制有几个1就是有几个不同的字母;(可以自行思考一下)
#include <bits/stdc++.h> using namespace std; const int MAXN=1e5+10; int tree[MAXN*4]; int tot=0; char s[MAXN]; char t[5]; int n; void build(int root,int l,int r){ if(l==r){ tree[root]=1<<(s[l]-‘a‘); return ; } int mid=(l+r)>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); tree[root]=tree[root<<1]|tree[root<<1|1]; } void gao(int root,int l,int r,int p,char x){ if(l==r){ int w=1<<(x-‘a‘); tree[root]=w; return ; } int mid=(l+r)>>1; if(p<=mid)gao(root<<1,l,mid,p,x); else gao(root<<1|1,mid+1,r,p,x); tree[root]=tree[root<<1]|tree[root<<1|1]; } int query(int root,int l,int r,int L,int R){ if(L>r||R<l)return 0; if(l>=L&&R>=r)return tree[root]; int mid=(l+r)>>1; int res=0; res|=query(root<<1,l,mid,L,R); res|=query(root<<1|1,mid+1,r,L,R); return res; } int main(){ scanf("%s",s+1); n=strlen(s+1); build(1,1,n); int T; scanf("%d",&T); while(T--){ int o; scanf("%d",&o); if(o==1){ int p; scanf("%d%s",&p,t); //cout<<p<<" "<<t[0]<<endl; gao(1,1,n,p,t[0]); } else { int l,r; scanf("%d%d",&l,&r); int res=query(1,1,n,l,r); int ans=0; while(res){ if(res&1)ans++; res>>=1; } printf("%d ",ans); } } return 0; }
F:
题意:水从(0,0)进,判断能否从(1,n)出;
解:虽然有6种管道,但是可以旋转,所以就可以看成两种管道;
dfs(x,y,last):x,y为当前位置,last表示从哪里留过来的;(写了大半个小时,改来改去,可能我写的有点繁琐,也懒得改了)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=2e5+10; int a[5][MAXN]; bool vis[5][MAXN]; string s; int n;//last up 1 down 2 left 3 bool dfs(int x,int y,int last){ //cout<<"x="<<x<<‘ ‘<<"y="<<y<<"last="<<last<<endl; if(!vis[x][y])return false; if(y==(n+1)&&x==2)return true; if(y>=(n+1))return false; if(x<1||x>2)return false; if(a[x][y]){ if(last==1||last==2){ vis[x][y+1]=true; if(dfs(x,y+1,3))return true; else vis[x][y+1]=false; } else if(last==3){ if(x==1){ vis[x+1][y]=true; if(dfs(x+1,y,1))return true; else vis[x+1][y]=false; } else { vis[x-1][y]=true; if(dfs(x-1,y,2))return true; else vis[x-1][y]=false; } } } else { if(last==3){ vis[x][y+1]=true; if(dfs(x,y+1,3))return true; else vis[x][y+1]=false; } } return false; } int main(){ ios::sync_with_stdio(false); int T; cin>>T; while(T--){ cin>>n; for(int i=1;i<=2;i++){ cin>>s; for(int j=0;j<n;j++){ if((s[j]-‘0‘)<=2)a[i][j+1]=0; else a[i][j+1]=1; vis[i][j+1]=false; } } vis[1][n+1]=vis[2][n+1]=false; vis[1][1]=true; if(dfs(1,1,3)){ cout<<"YES"<<endl; } else cout<<"NO"<<endl; } return 0; }
G:
题意:给n个区间,问是否存在一个区间,使得重叠k次,求最大的区间;
解:按区间的左端点排序,然后维护一个大小为k的按照右端点从小到大的队列。并且不断更新最小的right值。(新进来的right一定大于队首的right值),那么每个时刻的长度都是队首的right值 减去新进来的left值,不断更新结果。另外注意输出。
#include <bits/stdc++.h> using namespace std; const int MAXN=3e5+10; int n,k; struct node{ int l,r,id; }a[MAXN]; bool cmp(node x,node y){ return x.l==y.l?x.r<y.r:x.l<y.l; } priority_queue<int,vector<int>,greater<int> >que; int main(){ ios::sync_with_stdio(false); cin>>n>>k; for(int i=1;i<=n;i++){ cin>>a[i].l>>a[i].r; a[i].id=i; } sort(a+1,a+1+n,cmp); /*for(int i=1;i<=n;i++){ cout<<a[i].l<<‘ ‘<<a[i].r<<‘ ‘<<a[i].id<<endl; }*/ int ans=0; int L=a[1].l; for(int i=1;i<=n;i++){ que.push(a[i].r); if(que.size()>k)que.pop(); int res=que.top()-a[i].l+1; if(ans<res&&que.size()==k){ ans=res; L=a[i].l; } } cout<<ans<<endl; if(ans){ for(int i=1;i<=n;i++){ if(a[i].l<=L&&a[i].r>=L+ans-1){ cout<<a[i].id<<‘ ‘; k--; } if(!k)break; } cout<<endl; } else{ for(int i=1;i<=k;i++){ cout<<i<<‘ ‘; } cout<<endl; } return 0; }
以上是关于10/10的主要内容,如果未能解决你的问题,请参考以下文章