看到某神叉每天都关注访问量...所以我也来蹭热度了
不断学习别人的代码,才是一种进步,....同一个题...为什么他们的代码这么优秀>>觉得一是思路的问题,另外就是对问题的归纳程度,当然有又臭又长的代码,倒是显得有点幼稚了....其实从简单的方面去考虑问题,也是挺不错的,一时无法抉择
----------------------------------------------------------------------------------------------------------------------
题意: 给定一串数字,要求添加几个数字使得这些数字连续,求最小的添加量
解题代码:
#include<bits/stdc++.h> using namespace std; int a[1100]; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); int ans=a[n]-a[1]+1-n; printf("%d\n",ans); return 0; }
题意:给出a,b,x,y>> 求满足 0<=x0<=a ,0<=y0<=b,且 x0/y0=x/y的整点数>>
解题代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll gcd(ll a ,ll b){ if(b==0) return a; else return gcd(b,a%b); } int main(){ ll x,y,a,b,ans; cin>>a>>b>>x>>y; ll tmp=gcd(x,y); x/=tmp;y/=tmp; cout<<min(a/x,b/y); return 0; }
题意: 将n个组合分成m个组合,每个组合里任意两个数相差>=d(原组合不同则不必要) 求最小的m 贪心去做就好
set封装的二分应用
解题代码:
#include<bits/stdc++.h> using namespace std; typedef pair<int,int>pii; const int N=2e5+10; set<pii>se;int ans[N]; struct node{int x,y;}a[N]; bool cmp(node a,node b){return a.x<b.x;} int main(){ int n,m,d,x;scanf("%d%d%d",&n,&m,&d); for(int i=1;i<=n;i++){ scanf("%d",&x); se.insert({x,i}); } int t=0; while(se.size()!=0){ t++;auto u=se.begin();ans[u->second]=t; int pre=u->first;u=se.erase(u); while(u!=se.end()){ u=se.upper_bound({pre+d,n+1}); if(u==se.end()) break; else { ans[u->second]=t; pre=u->first; u=se.erase(u); } } } printf("%d\n",t); for(int i=1;i<=n;i++) printf("%d ",ans[i]); return 0; }
题意:在云层的最左端点跳肯定是最优的,枚举每个起点,二分找到右边满足要求的右端点.求最值就好
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; struct node{int x,y;}a[N]; bool cmp(node a,node b){return a.x<b.x;} int dis[N],sum[N]; int main(){ int n,h;scanf("%d%d",&n,&h); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i].x,&a[i].y); } sort(a+1,a+n+1,cmp); dis[1]=0;sum[1]=a[1].y-a[1].x;dis[n+1]=1e9+1000; for(int i=2;i<=n;i++){dis[i]=dis[i-1]+a[i].x-a[i-1].y;sum[i]=sum[i-1]+a[i].y-a[i].x;} int ans=0; for(int i=1;i<=n;i++){ int p=lower_bound(dis+i,dis+n+2,h+dis[i])-dis; ans=max(ans,sum[p-1]-sum[i-1]); } printf("%d\n",ans+h); return 0; }
E是一枚树上构造题,题意是给出n,同时给出n-1组(u,v) 代表去掉第i条边所分成的两个团中的最大节点值:
解法:首先v必须为n,其次考虑u,假如u出现一次,则将他与n节点连一条边,其次假如u出现多次的话,考虑这样构造,将n,u作为两个端点,中间依次
假如 比u小的值的节点(若不满足的话,则该情况不存在)
感觉优美的代码,思路特别清晰的代码...确实正确率很高,...一般思路不完善...代码会越丑....还不一定正确.....觉得写题前 还是得需要完整的思路
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int num[N];queue<int>q; struct node{int x,y;}ans[N]; int main(){ int n,x,y;scanf("%d",&n); int flag=1; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); if(y!=n) flag=0;num[x]++; } if(flag==0){puts("NO");return 0;} int cnt=1; for(int i=1;i<n;i++) if(num[i]==0) q.push(i); for(int i=1;i<n;i++) if(num[i]){ if(num[i]==1) ans[cnt++]={i,n}; else{ int p=i; while(num[i]!=1){ if(q.size()==0||q.front()>=i) { flag=0;puts("NO");return 0; } int v=q.front();q.pop(); ans[cnt++]={p,v};p=v;num[i]--; } ans[cnt++]={p,n}; } } puts("YES"); for(int i=1;i<n;i++){ printf("%d %d\n",ans[i].x,ans[i].y); } return 0; }
显然y是没什么用的.....
考虑同一条线上的两个寄存器的间隔的一半d 假设间隔是2kd的话 那么两条边上的点分别是{kd,3kd,5kd.....} {0,2kd,4kd,6kd,.......} 考虑k的取值,首先取不同值时,
肯定会有一些交点被包含另一种方案中,所以我们可以考虑从枚举间隔出发..
.....待补
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m,y,a[N],b[N]; map<int,int>cnt1,cnt2; int solve(int k){ cnt1.clear();cnt2.clear(); for(int i=1;i<=n;i++) cnt1[a[i]%k]++; for(int i=1;i<=m;i++) cnt2[b[i]%k]++; int ans=0; for(int i=1;i<=n;i++) ans=max(ans,cnt1[a[i]%k]+cnt2[(a[i]+k/2)%k]); for(int i=1;i<=m;i++) ans=max(ans,cnt2[b[i]%k]+cnt1[(b[i]+k/2)%k]); return ans; } int main(){ scanf("%d%d",&n,&y); for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d%d",&m,&y); for(int i=1;i<=m;i++) scanf("%d",&b[i]); int ans=0; for(int k=2;k<=1e9;k<<=1) ans=max(ans,solve(k)); printf("%d\n",max(ans,2)); return 0; }