1072 Div3练习

1072 Div3练习

今天是1.14,1.4且114

想回一下手感,但是。。。把CP editor装好了,但是感觉还是VScode更方便,不过在任何设备上都能敲上代码就足够了

A题不说了

B.Hourglass

这个题目思想很朴素,一开始题目没看明白想得太多就容易绕进去。

反正沙漏分两种情况,一个是(完全流完+空闲)周期性进行工作,这样直接计算即可。另一个是没有流完就翻过来了,但是这样仅仅只是把前一阶段流出来的 完完整整地流回去。所以只要抓住这两个阶段分析即可

新单词Hourglass

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define vi vector<int> 
#define pb push_back 
#define pii pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int INF=1e18,N=2e5,MOD=998244353;

void solve(){
    int n,k;
    cin>>n>>k;
    int l,r;
    l=r=n;int tm=0;
    
    while(r!=1){
        if(l<=k&&k<=r) break;
        tm++;
        l>>=1;
        r=(r>>1)+(r%2);
    } 
    if(l<=k&&k<=r) cout<<tm<<endl;
    else cout<<-1<<endl;
    return ;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T=1;
    cin>>T;
    while(T--)
        solve();
    return 0;
}

C.Huge Pile

这个题目一开始在想怎么判断10101里面有无100,但是实际上不用这样,二叉下来后直接分析是否落入区间即可,左端是>>1右端是>>1+%1

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define vi vector<int> 
#define pb push_back 
#define pii pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int INF=1e18,N=2e5,MOD=998244353;

void solve(){
    int n,k;
    cin>>n>>k;
    int l,r;
    l=r=n;int tm=0;
    
    while(r!=1){
        if(l<=k&&k<=r) break;
        tm++;
        l>>=1;
        r=(r>>1)+(r%2);
    } 
    if(l<=k&&k<=r) cout<<tm<<endl;
    else cout<<-1<<endl;
    return ;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T=1;
    cin>>T;
    while(T--)
        solve();
    return 0;
}

D.Unfair Game

这个题目题面就是一坨,目前想到的是alice的最优策略:初始时知道奇偶性,奇则-1,偶则/2,没有赢之前返回的总是x,x是尾0的个数,所以就进行x次/2,做完之后再-1把尾1消掉,对返回的x同上操作。

一开始已知n是一个2^d,所以我们只需要找到d的数值是什么即可,一个while循环就好了,显然对于一个二进制数,Alice要想把它变成0,除了最高位的1只需要最后的一次操作之外,其它位上的0需要一次>>1,1需要一次-1和一次>>1所以当这些次数加起来超过k时,就是可以选择的数,具体的1的位置数目可以使用组合数公式计算.

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define vi vector<int> 
#define pb push_back 
#define pii pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int INF=1e18,N=2e5,MOD=1e9+7;
int C[35][35];
void init(){
    for(int i=0;i<=30;i++){
        for(int j=0;j<=30;j++){
            if(i<j) C[i][j]=0;
            else if(j==0) C[i][j]=1;
            else C[i][j]=C[i-1][j-1]+C[i-1][j];
        }
    }
}

void solve(){
    int n,k;
    cin>>n>>k;
    int bits=0;
    while(n%2==0){
        n>>=1;
        bits++;
    }
    int ans=0;if(bits+1>k) ans++;
    for(int i=0;i<bits;i++)
        for(int j=1;j<=i+1;j++)
            if(i+j>k) ans+=C[i][j-1];
    cout<<ans<<endl;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    init();
    int T=1;
    cin>>T;
    while(T--)
        solve();
    return 0;
}

E.Exquisite Array

题目的意思是有一个长度为n的排列,一个k阶(单词不认识,暂且命名为阶好了)的数组是指任意两个相邻的数差的绝对值大于或等于k。然后我们要算出k从1到n-1的所有k阶数组(原数组的子数组)的个数。
当k为1时答案都是n(n-1)/2,也就是说对于我们知道了满足k的数组长度len时,它的任意子数组也满足k阶,数目一共为len(len-1)/2.而满足k+1阶的数组也一定满足k阶,所以我们就可以把原排列进行分段,一开始记录满足相邻差绝对值大于等于k的位置,然后在k递减的过程中逐步进行字段的合并即可,对于这个合并过程,可以用并查集来实现

//That's me.
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define vi vector<int> 
#define pb push_back 
#define pii pair<int,int>
#define fi first
#define se second
#define endl '\n'
const int INF=1e18,N=2e5,MOD=998244353;

vi sz,f;

int find(int x){
    if(f[x]==x) return x;
    f[x]=find(f[x]);
    return f[x];
}

void merge(int a,int b){
    int fa=find(a),fb=find(b);
    if(fa>fb) swap(fa,fb);
    sz[fa]+=sz[fb];
    f[fb]=fa;
}

int cal(int x){
    x=find(x);
    return sz[x]*(sz[x]-1)/2;
}

void solve(){
    int n;
    cin>>n;
    map<int,vi>mp;
    int pre=0;
    for(int i=0;i<n;i++){
        int t;
        cin>>t;
        if(i) mp[abs(t-pre)].pb(i);
        pre=t;
    }
    sz.resize(n);
    f.resize(n);
    for(int i=0;i<n;i++){f[i]=i;sz[i]=1;}
    vi ans;
    int cur=0;
    for(int i=n-1;i>0;i--){
        for(auto y:mp[i]){
            cur-=cal(y);
            cur-=cal(y-1);
            merge(y,y-1);
            cur+=cal(y);
        }
        ans.pb(cur);
    }
    reverse(ans.begin(),ans.end());
    for(int i=0;i<n-1;i++) cout<<ans[i]<<' ';
    cout<<endl;
    sz.clear();f.clear();
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T=1;
    cin>>T;
    while(T--)
        solve();
    return 0;
}
posted @ 2026-01-14 23:35  江蝶  阅读(2)  评论(0)    收藏  举报