codeforces1311E

题目链接

sol:先建一条链,然后把下面的点一个个往上面移, 优先移到最上面,如果上面满了就往下一层, 知道刚刚好凑满距离,如果最后不能移了就说明不能凑出给定的距离

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
#define fi first
#define se second
#define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
#define fd1(i,n) for ((i)=(n);(i)>=1;(i)--)
#define fz0g(i,n) for ((i)=0;(i)<=(n);(i)++)
#define fd0g(i,n) for ((i)=(n);(i)>=0;(i)--)
#define fz0k(i,n) for ((i)=0;(i)<(n);(i)++)
#define fd0k(i,n) for ((i)=(((long long)(n))-1);(i)>=0;(i)--)
#define fz(i,x,y) for ((i)=(x);(i)<=(y);(i)++)
#define fd(i,y,x) for ((i)=(y);(i)>=(x);(i)--)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();++itr)
#define pb push_back
#define mp make_pair
#define inf LLONG_MAX
#define iinf INT_MAX

const char al='\n';

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
#endif

    int T;
    cin>>T;
    while(T--) {
        int n,m,i,j;
        cin>>n>>m;
        vector<int>a(n+5);
        int jyl=0,wn=1,wq=n;
        fz1(i,n) {
            a[i]=1; jyl+=i-1;
        }
        while(jyl>m&&wq>wn+1) {
            int oo=jyl-m;
            if(wq-wn-1<=oo) {
                jyl-=wq-wn-1; a[wn+1]++; a[wq]--; wq--;
                if(a[wn+1]==(1<<wn)) wn++;
            }
            else {
                int x=wq-oo;
                if(a[x]<(1<<(x-1))) {
                    jyl-=oo; a[x]++; a[wq]--; wq--;
                }else break;
            }
        }
        if(jyl==m) {
            cout<<"YES"<<al;
            vector<int>fa,now; fa.pb(1);
            int index=1;
            fz(i,2,wq) {
                now.clear();
                fz1(j,a[i]) {
                    now.pb(++index); cout<<fa[j%fa.size()]<<" ";
                }fa=now;
            }cout<<al;
        } else cout<<"NO"<<al;
    }

    return 0;
}

 

posted @ 2023-07-13 16:01  yccdu  阅读(3)  评论(0编辑  收藏  举报