2022.6.16补题

受到昨天14题里8题数学的影响,今天鸽一天gym,将这几天做的gym里面的银牌题(50<x<100)补一补。

2022 Jiangsu Collegiate Programming Contest

链接:https://codeforces.com/gym/103743

原来AC:A  I  K  罚时:207min

 

 补题:C  J   

C:(单调队列)

单调队列前置知识点:

单调队列:
有n个生物,第i个生物会在第i到ai(i<=ai<=n)天出现(对于所有i(1<i<n),满足ai<=ai+1),它的攻击力是bi(1<=bi<=100000)。请输入每天出现的生物的攻击力最大值

思路:1.假设现在已经到了第i天,对于第j个生物(j<i),if(bj<bi),那么第j个生物不再考虑。
2.我们使用一个队列,按照编号从小到大的顺序,存一下到目前为止,哪些生物是需要被考虑的。
3.队列里面生物的攻击力是单调递减的,why?
Because 根据思路1,在队列中不可能存在后面的比前面的强,那么前面的那个不会入队
So,每次攻击力最高的都在队首。

opeartion:
1.加入一个生物,队列末尾比它攻击力低的生物不用考虑;
2.把队列末尾比它攻击力低的生物删除以后,加入队尾;
3.队首消失,则删除队首

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int maxn=1e5+30;
int n,a[maxn],b[maxn],c[maxn][2];//c数组模拟队列
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)    cin>>a[i]>>b[i];
    int k=0,l=1;//l为头指针,k为尾指针
    for(int i=1;i<=n;i++){
        for(;k>=l&&b[i]>=c[k][0];k--);//把队列末尾比它攻击力低的生物删除
        c[++k][0]=b[i];//++k,队尾加一位
        c[k][1]=a[i];//记录状态
        cout<<c[l][0]<<"\n";
        for(;k>=l&&c[l][1]==i;l++);//l++就是删除队首,看队首元素是否消失
    }
    return 0;    
}

C的题面:

Tom最近喜欢玩电子游戏。游戏规则如下:
游戏在x轴上进行。游戏中一共有n+1根柱子,被从左到右放置。柱子的编号从0~n。编号为i的支柱坐标为x=i。也有范围在[n+1,inf]的无限大的平台。玩家如果跳到这块区域里面就算胜利。
玩家从0号柱子开始,并且只能从左向右跳跃。即玩家们的坐标必须一直增加。并且他只能跳到平台的柱子上,否则他会掉到空白区域,输掉游戏。此外,他的跳跃能力是有限的。每次跳跃的距离不超过p。

除了0号柱子,剩下的每根柱子上都会有一个宝箱。在i号柱子上有ai金币。但是,也有一些陷阱(ai<0),这样Tom会损失-ai金币。

游戏有n级。Tom只能跳到第i级以i的倍数编号的柱子上。现在有q个询问,每一个包含一个数x,询问Tom如果在x级获胜,他能取得的数量最多的金币。Tom得到负数个金币也是有可能的。

输入
n(柱子数量) q(问题数量) p(最长跳跃距离)
a1~an
q行,一行一个x

输出

得到的金币的最大数量
不能赢,cout<<"Noob"<<"\n";

思路:

C题的DP式子很简单,就是令f[i]表示在i位置的最大值,有f[i]=max{f[i−k⋅j]}(k⋅j≤p),其中j表示当且为j级。
注意:此题不能用线段树,多个logn会TLE。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double db;
const int maxn=1e6+30;
const LL inf=1e18+30;
vector<int> qry[maxn];
vector<LL> v;
LL a[maxn],ans[maxn];
int qq[maxn];
int ll,rr;//l头指针,r尾指针
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n,q,p;
    cin>>n>>q>>p;
    for(int i=1;i<=n;i++)    cin>>a[i];
    for(int i=1;i<=q;i++){
        int x;
        cin>>x;
        if(x>p)    ans[i]=-inf;
        else qry[x].push_back(i);
    }
    for(int i=1;i<=n;i++){
        if(qry[i].size()){//x>p不考虑直接cout<<"Noob"<<"\n";
            v.clear();
            v.push_back(0);
            for(int j=i;j<=n;j+=i)    v.push_back(j);
            v.push_back(n+1);
            vector<LL> f(v.size()+30,-inf);
            f[0]=0;
            ll=0,rr=-1;
            qq[++rr]=0;
            for(int j=1;j<v.size();j++){
                while(ll<=rr&&v[j]-v[qq[ll]]>p)    ll++;//头指针+1,删除队首
                f[j]=max(f[j],f[qq[ll]]+a[v[j]]);//DP式子
                while(ll<=rr&&f[qq[rr]]<=f[j])    rr--;//尾指针-1,入队尾
                qq[++rr]=j;
            }
            for(auto j:qry[i])    ans[j]=f[v.size()-1];
        }
    }
    for(int i=1;i<=q;i++){
        if(ans[i]==-inf)    cout<<"Noob"<<"\n";
        else    cout<<ans[i]<<"\n";    
    }
    return 0;
}

J

J(平衡树)(递推,数学优化)
一棵二叉树是超级平衡的如果T是空的或者同时满足以下三个条件:
1.左子树是超级平衡的
2.右子树是超级平衡的
3.左子树和右子树的节点数最多相差1个。

计算有n个节点的超级平衡树的数量,答案%(1<<64)。

输入
T个样例

n(树上的节点)

输出
超级平衡树的数量

思路:找递推关系

设f[x]是n个点的超级平衡树的个数,则:

x==0 f[x]=1;//empty

x为偶数:f[x]=2*f[(x/2-1]*f[x/2];
x为奇数:f[x]=f[(x-1)/2]*f[(x-1)/2];
数组不能开到1<<64,所以尝试数学方法

 

 

然后根据递推式子写出dfs函数。

注意此题的数据,要unsigned long long!!!

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
ull dfs(ull x,ull a,ull b,ull c){
    if(x==0)    return 0;
    if(x==1)    return c;
    if(x&1)    return dfs(x>>1,2*a+b,b,c+b);
    else    return dfs(x>>1,a,a+b*2,c+a);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T;
    cin>>T;
    while(T--){
        ull n;
        cin>>n;
        ull ans=1;//empty
        ull c=dfs(n,1,0,0);
        if(c>=64)    ans=0;
        else    ans<<=c;
        cout<<ans<<"\n";
    }
    return 0;
}

 

The 17th Heilongjiang Provincial Collegiate Programming Contest的L和2022 Hubei Provincial Collegiate Programming Contest的J均是字符串哈希,明天整理字符串哈希相关题目。(QAQ)

只剩下The 19th Zhejiang Provincial Collegiate Programming Contest的J题和2020-2021 ICPC - Gran Premio de Mexico - Repechaje的 C   D   E

下午完成了Java大作业,晚上准备休息换换脑子了,明天一套gym…………

 

posted @ 2022-06-16 20:15  cf不上1500不改名  阅读(148)  评论(0)    收藏  举报