给n个数,两个数之间相或,后减去后一个数,求如何排序,使得最终结果越大。
发现只要找出一个最优的数后,其余数顺序任意,因为,一旦有两个数,同时有1出现在同一位上,则不论如何计算该位必为0。
第一个数,应为在所有数中,二进制单独只为1,所表示的10进制数最大,即为最优解。
没有只有一位1有个1的话 输出原顺序
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const double eps=1e-10;
const ll mod=1e9+7;
#define endl '\n'
ll T,n,k,q,a[maxn],dp[maxn];
void f(ll x){
ll cnt=0;
while(x){
if(x&1){
dp[cnt]++;
}
cnt++;
x/=2;
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
f(a[i]);
}
for(int i=30;i>=0;i--){
if(dp[i]==1){
for(int j=1;j<=n;j++){
if((a[j]/(1<<i))&1){
cout<<a[j]<<" ";
for(int k=1;k<=n;k++){
if(k!=j)
cout<<a[k]<<" ";
}
cout<<endl;
return 0;
}
}
}
}
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
https://codeforces.com/contest/1300/problem/D
使得P T相似 只能偶数个点的对称图形
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const double eps=1e-10;
const ll mod=1e9+7;
#define endl '\n'
ll T,n,k,q,a[maxn],b[maxn],f;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
}
if(n&1) //P T相似 偶数个点 对称图形
cout<<"NO"<<endl;
else{
ll dx=a[1]+a[1+n/2],dy=b[1]+b[1+n/2];
for(int i=2;i<=n/2;i++){
if(a[i]+a[i+n/2]!=dx || b[i]+b[i+n/2]!=dy){
f=1;
break;
}
}
if(f)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}
E
单调递减栈
该段第i个数的段的长度倍<=该段前缀和 top–
就是把某个区间的数字都变成这个区间数字和的平均数,可以操作多次,问最小的字典序。’
4
7 5 5 7
5.666666667
5.666666667
5.666666667
7.000000000
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
double a[maxn],s[maxn];
ll n,st[maxn];
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lf",&a[i]);
s[i]=s[i-1]+a[i];
}
ll top=1;
st[top]=0;
for(int i=1;i<=n;i++){
while(top>1 && (s[i]-s[st[top]])*(i-st[top-1])<=(s[i]-s[st[top-1]])*(i-st[top])) top--;
st[++top]=i;//st[1]=0 st[2]=3 st[3]=4
}
for(int i=1;i<top;i++){
double res=(s[st[i+1]]-s[st[i]])/(st[i+1]-st[i]);
for(int j=1;j<=st[i+1]-st[i];j++){
printf("%.9f\n",res);
}
}
return 0;
}