标签:欧几里得 code oom ssi 不同 efi -- foo put
从前往后,或者从后往前枚举下该位置一二层各走一次
#include<bits/stdc++.h> using namespace std; #define int long long #define sc(x) scanf("%I64d",&x); #define pb push_back #define fi first #define se second #define P pair<int,int> #define si signed char s[1005]; int n; si main() { int t; sc(t); while(t--){ sc(n); scanf("%s",s+1); int ans=0; int p=0,t=0; for(int i=1;i<=n;i++){ if(s[i]==‘1‘){ t+=1; } } if(t==n){ cout<<2*t<<‘\n‘; }else{ ans=2*t+n-t; if(t==0){cout<<n<<‘\n‘;continue;} int ed= 0; for(int i=n;i>=1;i--){ if(s[i]==‘1‘){ ed= i; break; } } p=0; for(int i=1;i<=ed;i++){ if(s[i]==‘1‘){ ans=max(ans,p+2*(ed-i+1)); p+=2; } else {ans=max(ans,p+2*(ed-i+1));p++;} } ed =1; for(int i=1;i<=n;i++){ if(s[i]==‘1‘){ ed= i; break; } } p=0; for(int i=n;i>=ed;i--){ if(s[i]==‘1‘){ ans=max(ans,p+2*(i-ed+1)); p+=2; } else {ans=max(ans,p+2*(i-ed+1));p++;} } cout<<ans<<‘\n‘; } } }
给定 n,p,w,d;w<d
要求
x⋅w+y⋅d=p
x+y+z =n
即
x⋅w+y⋅d=p
x+y< =n
被扩展欧几里得坑了==
数据范围爆long long
先求下__gcd(w,d) ,如果p%__gcd(w,d)!=0,直接判无解
容易发现x越大,x+y就会越大
然后x从p/w+1往0开始枚举,不超过d的范围一定能找到合适的解
如果没找到,说明不能满足x+y<=n,输出-1
#include<bits/stdc++.h> using namespace std; #define int long long signed main() { int n,p,d,w; scanf("%I64d%I64d%I64d%I64d",&n,&p,&w,&d); int a =__gcd(w,d); if(p%a!=0||p/w>n){ cout<<"-1"<<endl;return 0; } for(int i = p/w+1,j=0;i>=0&&j<10*d;j ++,i--){ if((p-i*w)%d==0){ int x= (p-i*w)/d; if(x+i<=n&&x>=0){ cout<<i<<‘ ‘<<x<<‘ ‘<<n-i-x<<endl; return 0; } } } cout<<-1<<‘\n‘; }
一棵树要求任意一条三长路上的三个点颜色不同
所以只能是一条链
记录下祖父,父节点颜色,dfs跑几遍就行
#include<bits/stdc++.h> using namespace std; #define int long long #define sc(x) scanf("%I64d",&x); #define pb push_back #define fi first #define se second #define P pair<int,int> #define si signed vector<int>G[100005]; int C[100005][3]; int A[100005]; int B[100005]; int n; void dfs(int x,int fa,int pa) { for(int i=0; i<3; i++) { if(i!=A[fa]&&i!=A[pa]) { A[x]=i; break; } } for(int i=0; i<G[x].size(); i++) { if(G[x][i]!=fa) { dfs(G[x][i],x,fa); } } } si main() { sc(n); for(int i=0; i<3; i++) { for(int j=1; j<=n; j++) { sc(C[j][i]) } } int a,b; for(int i=1; i<n; i++) { sc(a) sc(b); G[a].pb(b); G[b].pb(a); if(G[a].size()>2||G[b].size()>2) { puts("-1"); return 0; } } A[0]=-1; /*cout<<dfs(1,0,0)<<endl; for(int i=1;i<=n;i++){ cout<<B[i]+1<<‘ ‘; }*/ for(int i=1; i<=n; i++) { if(G[i].size()==1) { int a=i,b=G[a][0],c=((G[b][0]==a)?G[b][1]:G[b][0]); int ans=1e18; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { int t=0; if(i!=j) { A[a]=i; A[b]=j; dfs(c,b,a); for(int i=1; i<=n; i++) { t+=C[i][A[i]]; } if(ans>t) { ans=t; for(int i=1; i<=n; i++)B[i]=A[i]; } } } } cout<<ans<<‘\n‘; for(int i=1; i<=n; i++) { cout<<B[i]+1<<‘ ‘; } return 0; } } }
这题似曾相识
给一个数组,k次操作,每次操作可以选择一个数加一或者减一
求不超过k次操作后,该数组最大值最小值之差最小为多少
思路:
sort 维护一下前缀和
二分答案
check:
从左至右
滑动窗口,对每一个数字Ai,枚举它是下界,Ai+x是上界时的代价,取min
然后从右至左
判断一下最小代价是否大于k
#include<bits/stdc++.h> using namespace std; #define int long long #define sc(x) scanf("%I64d",&x); #define si signed int n,k; int A[100005]; int B[100005]; bool check(int x) { int t=1e18; int y=n,z=1; int i=n,cnt=0; // cout<<x<<"xxxxxxxxxxx"<<endl; while(y>=1) { if(i==0)i=1; for(i; i>=1; i--) { if(A[y]-A[i]>x) { t =min(t,(A[y]-x)*i-B[i]+cnt); //cout<<t<<" "<<i<<endl; break; } } cnt=(B[n]-B[y-1]-A[y-1]*(n-y+1)); y--; } cnt=0; i=1; while(z<=n) { if(i>n)i=n; for(i; i<=n; i++) { if(A[i]-A[z]>x) { t =min(t,B[n]-B[i-1]-(A[z]+x)*(n-i+1)+cnt); break; } } cnt=A[z+1]*z-(B[z]); z++; } //cout<<t<<endl; return t<=k; } si main() { sc(n); sc(k); for(int i=1; i<=n; i++) { sc(A[i]) } sort(A+1,A+1+n); int l = 0,r=A[n]-A[1]; for(int i=1; i<=n; i++){B[i]=A[i]+B[i-1];} while(l+1<=r) { int mid =(l+r)/2; if(check(mid)) { r=mid; } else { l=mid+1; } } cout<<l<<endl; /*int ans = A[n]-A[1]; for(int i=0; i<=n; i++) { if(k<((A[i]*i)-B[i])) { break; }//min k-=(A[i]*i)-B[i]; int l=i,r=n; while(l+1<=r) { int mid=(l+r)/2; if(B[n]-B[mid]-(n-mid)*A[mid]<=k) { r = mid; } else { l = mid+1; } } int x= A[l-1],y=A[l]; if(l-1<i){ x=A[l]; } while(x+1<=y) { int mid =(x+y)/2; if(B[n]-B[l-1]-(n-l+1)*mid<=k) { y=mid; } else { x=mid+1; } } int cnt=A[i]; if(k-B[n]+B[l-1]+(n-l+1)*x>l-1&&l-1>0){ cnt+=min(k/(l-1),x-A[i]); } ans=min(x-cnt,ans); } cout<<ans<<‘\n‘;*/ }
Codeforces Round #592 (Div. 2)
标签:欧几里得 code oom ssi 不同 efi -- foo put
原文地址:https://www.cnblogs.com/liulex/p/11781092.html