質問:操作f(x、y)=(x | y)−yを定義し、再配列を要求する配列を提供して、この操作を順番に実行した後の答えが最大になるようにします
アイデア:演算のビット演算を観察します。いくつかの演算を手動でプッシュした後、この演算が完了した後、yのそれぞれが0であることがわかり、f(x、y)= x-(x&y)が計算されます。したがって、配列が順番に操作された場合、結果は最初の数字から後続の数字を引いたものになるため、答えが最大の場合は、最大の次の数字を差し引いて、配列の最初の数字を満たす必要があります。番号の最大桁数は1桁で、次の番号の順序は関係ありません。
コード:
#include <bits/stdc++.h>
#define x first
#define y second
#define mid (l + r >> 1)
#define lo (o << 1)
#define ro (lo | 1)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
struct tri{int x,y,z;};
int sum[35],arr[maxn];
int main()
{
// freopen("in.txt","r",stdin);
int n;scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",arr+i);
int tmp=arr[i];
for(int j=0;tmp;j++)
{
sum[j]+=tmp&1;
tmp>>=1;
}
}
int id=-1;//单独位的最高位
for(int i=0;i<35;i++)
if(sum[i]==1)id=i;
if(~id)for(int i=0;i<n;i++)
if(arr[i]&1<<id)swap(arr[0],arr[i]);
for(int i=0;i<n;i++)
printf("%d ",arr[i]);
return 0;
}
質問の意味:n面の形状の場合、n点が反時計回りに指定されていることを確認し、原点を中心とした平行移動によって形成されるn面の形状が元の形状と同じかどうかを確認します。
アイデア:推測をシミュレートするために絵を描き、結論を導き出します。図が中心対称である場合のみ可能です。それ以外の場合はできません。中心対称性を判断する方法は、i番目のベクトルとi + n / 2番目のベクトルが
コード:
#include <bits/stdc++.h>
#define x first
#define y second
#define mid (l + r >> 1)
#define lo (o << 1)
#define ro (lo | 1)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
struct tri{int x,y,z;};
pii arr[maxn];
int n;
pii operator+(pii a,pii b)
{
return pii({a.x+b.x,a.y+b.y});
}
bool solve()
{
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d%d",&arr[i].x,&arr[i].y);
arr[n]=arr[0];
if(n&1)return 0;
for(int i=0;i<n/2;i++)
{
if(arr[i]+arr[i+n/2]!=arr[i+1]+arr[i+n/2+1])return 0;
}
return 1;
}
int main()
{
// freopen("in.txt","r",stdin);
if(solve())puts("yes");
else puts("no");
return 0;
}
質問:n個の数値を指定すると、任意の間隔で数値を平均化できるため、操作後に取得できる最小の辞書式順序を見つけることができます。
アイデア:線分ツリーのように見えますが、実際には貪欲によってのみ解決できます。質問の焦点は、辞書式順序が最小であるため、qは前の値を可能な限り小さくする必要があることです。純粋に貪欲なアプローチを考えることができます。最終的な回答は昇順である必要があると簡単に推測できます。 2つの数値が降順の場合、2つの数値を結合する必要があるため、昇順を取得する1つの方法は、隣接する2つの数値のサイズ関係を前から後ろに判断することです。現在の数値が後者より大きい場合は、2つの山を結合します、そしてマージ後、前のものよりも小さい場合、前のものと前のものをマージし、それぞれが昇順になり、マージできなくなるまで。
ここで、pair <double、int>は各パイルの情報を格納するために使用され、doubleは平均値、intは数値、そして最後に順番に出力されます。
コード:
#include <bits/stdc++.h>
#define x first
#define y second
#define mid (l + r >> 1)
#define lo (o << 1)
#define ro (lo | 1)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<double, int> pdi;
typedef vector<int> vi;
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
struct tri{int x,y,z;};
pdi ans[maxn];
int tot=0,n;
int main()
{
// freopen("in.txt","r",stdin);
ans[0]={0,0};
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int a;scanf("%d",&a);
ans[++tot]={a,1};
while(ans[tot].x<=ans[tot-1].x)
{
ans[tot-1].x=ans[tot-1].x*ans[tot-1].y+ans[tot].x*ans[tot].y;
ans[tot-1].y+=ans[tot].y;
ans[tot-1].x/=ans[tot-1].y;
tot--;
}
}
for(int i=1;i<=tot;i++)
for(int j=0;j<ans[i].y;j++)
printf("%.15lf\n",ans[i].x);
return 0;
}