Codeforces Round#618(部分的)

アヌは機能を持っています

質問:操作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番目のベクトルが\ overrightarrow {i} + \ overrightarrow {i + n / 2} == 0

コード:

#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;
}

 

おすすめ

転載: blog.csdn.net/qq_43700916/article/details/104244982