首页 > 其他分享 >20241016 模拟赛(最终测试,空间跳跃,快速访问,门童)

20241016 模拟赛(最终测试,空间跳跃,快速访问,门童)

时间:2024-10-27 11:44:14浏览次数:7  
标签:20241016 快速访问 int ll mxn dep maxn define 门童

看题目戳这里

总结

时间分配:早自习20min。听歌60min,游走60min。100min考试。
t1看了40min没看出来转t2,t2打了一半发现负数没想出来,最后二三十分钟打t3暴力,结果神奇般地0pts,因为根节点深度设为1。当然t4没看一眼。唉。
下次打模拟赛的时候把耳机摘了。
结果:30+0+0+0
总结:wssb

解析

A. 最终测试

难度:绿
我觉得很不错的概率期望题。
第 \(i\) 名的同学的期望排名 \(E_i=1+\sum_{1\leq j\leq n,j\neq i}P(s_j>s_i)\)。
而 \(P(s_j>s_i)=\frac{1}{16}\sum\limits_{0\leq f_1,f_2\leq1}\sum\limits_{0\leq g_1,g_2\leq1,i\neq j}[f_1a_{i,1}+f_2a_{i,2}<g_1a_{j,1}+g_2a_{j,2}]\)。
为什么要乘 \(\frac{1}{16}\)?因为这里每个人的不同成绩被重复算进去了。有点难想,不过可以猜结论。
我们排序再二分一下就行,复杂度 \(O(n\log n)\)。

当时看的时候想到了排序,但不知道处理排名。有时候还是要大胆一点猜结论。


#include<bits/stdc++.h>
#define mxn 100010
#define ll long long
using namespace std;
ll n,a[mxn][4];
ll sc[mxn*4],cnt,ans[mxn];
int main(){
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i][1]>>a[i][2];
        a[i][0]=20000;
        a[i][1]=20000-a[i][1],a[i][2]=20000-a[i][2];
        a[i][3]=a[i][1]+a[i][2]-20000;
        sc[cnt++]=a[i][0],sc[cnt++]=a[i][1];
        sc[cnt++]=a[i][2],sc[cnt++]=a[i][3];
    }
    sort(sc,sc+cnt);
    for(int i=1;i<=n;i++){
        for(int j=0;j<4;j++){
            int rak=lower_bound(sc,sc+cnt,a[i][j])-sc;
            for(int k=0;k<4;k++)
                if(a[i][k]>a[i][j])rak--;
            ans[i]+=rak;
        }
    }
    for(int i=1;i<=n;i++)
        cout<<fixed<<setprecision(8)<<ans[i]/16.0+1<<'\n';
    return 0;
}   

B. 空间跳跃

难度:绿
容易发现 \(n>0\) 的时候就是角谷猜想,然后 \(n<0\) 的时候不知道怎么搞被迫换题。。。
实际上 \(n<0\) 的时候必会跳到 \(-1,-5,-17\) 中的一个(这是怎么看出来的???)
剩下的看代码。


#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define mxn 1510
using namespace std;
ll q,d,l,nega[mxn],ncnt=1501;
vector<int> ans;
void solve(int n){
    ans.clear();
    ans.pb(n);
    while(n!=0&&n!=1&&n!=-1&&n!=-5&&n!=-17){
        if(n%2)n=n*3+1;
        else n/=2;
        ans.pb(n);
    }
    while(n<=0){
        n+=d;
        ans.pb(n);
    }
    while(n!=1){
        if(n%2)n=n*3+1;
        else n/=2;
        ans.pb(n);
    }
    cout<<ans.size()-1<<' ';
    for(int i=ans.size()-1;i>=0;i--)
        cout<<ans[i]<<' ';
    cout<<'\n';
}
int main(){
    freopen("jump.in","r",stdin);
    freopen("jump.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>q>>d>>l;
    for(int i=1;i<=q;i++){
        int n;
        cin>>n;
        solve(n);
    }
    return 0;
}

C. 快速访问

难度:蓝
我们知道,\(dis_{i,j}=dep_i+dep_j-2*dep_{lca(i,j)}\)。
维护一个点集 \(S\) 为对于点 \(i\),满足题意的点。则有:
\(\sum\limits_{j\in S}dis_{i,j}=|S|dep_i+\sum\limits_{j\in S}dep_j-2*\sum\limits_{j\in S}dep_{lca(i,j)}\)
加上一个平方即为:
\(dis_{i,j}^2=dep^2_i+dep^2_j+4*dep_{lca(i,j)}^2-4*dep_idep_{lca(i,j)}-4*dep_jdep_{lca(i,j)}+2*dep_idep_j\)
三项就变成了六项,用树链剖分维护即可。
树剖+线段树复杂度 \(O(n\log^2n)\)。


#include<bits/stdc++.h>
#define mxn 200010
#define pb push_back
#define ll long long
using namespace std;
int n,q;
ll fa[mxn],sze[mxn],top[mxn],son[mxn],dep[mxn];
ll dfn[mxn],id[mxn],cnt;
vector<int> t[mxn];
void dfs1(int u,int f){
    fa[u]=f,sze[u]=1;
    for(int i=0;i<t[u].size();i++){
        int v=t[u][i];
        if(v==f)continue;
        dep[v]=dep[u]+1;
        dfs1(v,u);
        sze[u]+=sze[v];
        if(sze[son[u]]<sze[v])son[u]=v;
    }
    return;
}
void dfs2(int u,int f,int tp){
    id[u]=++cnt;
    dfn[cnt]=u,top[u]=tp;
    if(son[u]!=n+1)dfs2(son[u],u,tp);
    for(int i=0;i<t[u].size();i++){
        int v=t[u][i];
        if(v==f||v==son[u])continue;
        dfs2(v,u,v);
    }
    return;
}
struct seg_tree1{
    ll sum[mxn<<2]={0},lazy[mxn<<2]={0};
    void push_up(int rot){
        sum[rot]=sum[rot<<1]+sum[rot<<1|1];
    }
    void push_down(int rot,int l,int r){
        if(!lazy[rot])return;
        int mid=(l+r)>>1;
        sum[rot<<1]+=lazy[rot]*(mid-l+1);
        sum[rot<<1|1]+=lazy[rot]*(r-mid);
        lazy[rot<<1]+=lazy[rot];
        lazy[rot<<1|1]+=lazy[rot];
        lazy[rot]=0;
    }
    void add(int rot,int l,int r,int x,int y,ll k){
        if(l>=x&&r<=y){
            sum[rot]+=k*(r-l+1);
            lazy[rot]+=k;
            return;
        }
        push_down(rot,l,r);
        int mid=(l+r)>>1;
        if(mid>=x)add(rot<<1,l,mid,x,y,k);
        if(mid<y)add(rot<<1|1,mid+1,r,x,y,k);
        push_up(rot);
    }
    ll query(int rot,int l,int r,int x,int y){
        if(l>=x&&r<=y)return sum[rot];
        push_down(rot,l,r);
        ll ans=0;
        int mid=(l+r)>>1;
        if(mid>=x)ans+=query(rot<<1,l,mid,x,y);
        if(mid<y)ans+=query(rot<<1|1,mid+1,r,x,y);
        return ans;
    }
}tre1,tre2;
struct seg_tree2{
    ll sum[mxn<<2]={0},lazy[mxn<<2]={0},val[mxn<<2]={0};
    void push_up(int rot){
        sum[rot]=sum[rot<<1]+sum[rot<<1|1];
    }
    void push_down(int rot,int l,int r){
        if(!lazy[rot])return;
        int mid=(l+r)>>1;
        sum[rot<<1]+=lazy[rot]*val[rot<<1];
        sum[rot<<1|1]+=lazy[rot]*val[rot<<1|1];
        lazy[rot<<1]+=lazy[rot];
        lazy[rot<<1|1]+=lazy[rot];
        lazy[rot]=0;
    }
    void build(int rot,int l,int r){
        if(l==r){
            val[rot]=dep[dfn[l]]*2-1;
            return;
        }
        int mid=(l+r)>>1;
        build(rot<<1,l,mid);
        build(rot<<1|1,mid+1,r);
        val[rot]=val[rot<<1]+val[rot<<1|1];
    }
    void add(int rot,int l,int r,int x,int y,int k){
        if(l>=x&&r<=y){
            sum[rot]+=k*val[rot];
            lazy[rot]+=k;
            return;
        }
        push_down(rot,l,r);
        int mid=(l+r)>>1;
        if(mid>=x)add(rot<<1,l,mid,x,y,k);
        if(mid<y)add(rot<<1|1,mid+1,r,x,y,k);
        push_up(rot);
    }
    ll query(int rot,int l,int r,int x,int y){
        if(l>=x&&r<=y)return sum[rot];
        push_down(rot,l,r);
        ll ans=0;
        int mid=(l+r)>>1;
        if(mid>=x)ans+=query(rot<<1,l,mid,x,y);
        if(mid<y)ans+=query(rot<<1|1,mid+1,r,x,y);
        return ans;
    }
}tre3;
namespace sol{
    ll num,sum1,sum2;
    void add(int x,int val){
        num+=val,sum1+=val*dep[x],sum2+=val*dep[x]*dep[x];
        int tmp=x;
        while(x!=-1){
            tre1.add(1,1,n,id[top[x]],id[x],val);
            tre2.add(1,1,n,id[top[x]],id[x],val*dep[tmp]);
            tre3.add(1,1,n,id[top[x]],id[x],val);
            x=fa[top[x]];
        }
    }
    ll query(int x){
        ll ans=0,tmp=x;
        ans+=num*dep[x]*dep[x];
        ans+=sum2;
        ans+=2ll*dep[x]*sum1;
        ll ret1=0,ret2=0,ret3=0;
        while(x!=-1){
            ret1+=tre1.query(1,1,n,id[top[x]],id[x]);
            ret2+=tre2.query(1,1,n,id[top[x]],id[x]);
            ret3+=tre3.query(1,1,n,id[top[x]],id[x]);
            x=fa[top[x]];
        }
        ans-=4ll*dep[tmp]*ret1;
        ans-=4ll*ret2;
        ans+=4ll*ret3;
        return ans;
    }
}
int main(){
    freopen("visit.in","r",stdin);
    freopen("visit.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>q;
    son[0]=n+1,dep[0]=1;
    for(int i=1;i<=n;i++){
        son[i]=n+1;
        int u,v;cin>>u>>v;
        t[u].pb(v),t[v].pb(u);
    }
    dfs1(0,-1);
    dfs2(0,-1,0);    
    tre3.build(1,1,n);
    sol::add(0,1);
    for(int i=1;i<=n;i++){
        if(i-q-1>=1)sol::add(i-q-1,-1);
        cout<<sol::query(i)<<'\n';
        sol::add(i,1);
    }
    return 0;
}

D. 门童

难度:紫
首先,题目中有 \(x_{1,0}+x_{0,1}\geq 2*x_{0,0}\)。所以走一半再返回大门是不明智的。离开大门后一定要在沙发上休息一段时间后再回来。

所以可以设 \(dp(i)\) 为时刻 \(i\) 在门口,且接待完所有 \(t_j\leq i\) 选手的最大开心度。考虑上次转移时时刻为 \(k\),则有两种情况,一种是到沙发上打摆,一种是一直站门口。

然后我们会发现关键时刻只有 \(0,t_i,t_i+p_i\)。所以可以离散化一下,复杂度 \(O(n^2)\)。

我最多想到这里。solution说用李超树,我也不会,把题目搬上来吧。


#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fll
#define maxn 202020
using namespace std;
ll t[maxn],a[maxn],b[maxn],c[maxn],L[maxn];
ll N[maxn],K[maxn],B[maxn],dp[maxn];
ll left_i[maxn],right_i[maxn];
struct lichao_tree{
    struct line{
        ll k,b;
    }tr[maxn*4];
    void init(int n){
        for(int i=0;i<=4*n;i++) 
            tr[i].k=0,tr[i].b=-inf;
    }
    void add(int L,int R,ll k,ll b,int l,int r,int rt){
        if(L<=l&&r<=R){
            int mid=(l+r)/2;
            bool bl=((k*t[l]+b)<=(tr[rt].k*t[l]+tr[rt].b));
            bool br=((k*t[r]+b)<=(tr[rt].k*t[r]+tr[rt].b));
            if(bl&&br)return;
            else if(!bl&&!br){ 
                tr[rt]=(line){k,b}; 
                return;
            }
            else{
                bool bm=(k*t[mid]+b)<=(tr[rt].k*t[mid]+tr[rt].b);
                line li=(line){k,b};
                if(!bm)li=tr[rt],tr[rt]=(line){k,b};
                if((!bm&&bl)||(bm&&!bl)) 
                    add(L,R,li.k,li.b,l,mid,rt<<1);
                else add(L,R,li.k,li.b,mid+1,r,rt<<1|1);
            }
            return;
        }
        int mid=(l+r)/2;
        if(L<=mid)add(L,R,k,b,l,mid,rt<<1);
        if(mid<R)add(L,R,k,b,mid+1,r,rt<<1|1);
    }
    ll ask(int p,int l,int r,int rt){
        if(l==r)return tr[rt].k*t[p]+tr[rt].b;
        int mid=(l+r)/2;
        ll ans=tr[rt].k*t[p]+tr[rt].b;
        if(p<=mid)ans=max(ans,ask(p,l,mid,rt<<1));
        else ans=max(ans,ask(p,mid+1,r,rt<<1|1));
        return ans;
    }
}S1,S2;
int main(){
    // freopen("doorman.in","r",stdin);
    // freopen("doorman.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int tot=0,n,l; 
    cin>>n>>l;
    int x[4];
    for(int i=0;i<4;i++)
        cin>>x[i];
    t[tot++]=0;
    for(int i=1;i<=n;i++){
        cin>>a[i]>>b[i]>>c[i];
        t[tot++]=a[i];
        t[tot++]=a[i]+b[i];
    }
    sort(t,t+tot);
    tot=unique(t,t+tot)-t;//排序加去重
    for(int i=1;i<=n;i++){
        int l=lower_bound(t,t+tot,a[i])-t;
        int r=lower_bound(t,t+tot,a[i]+b[i])-t;
        L[r]=max(L[r],l*1ll);
        N[l]++;
        K[l]+=c[i];
        B[l]+=c[i]*(a[i]+b[i]);
    }
    for(int i=1;i<tot;i++){
        L[i]=max(L[i],L[i-1]);
        N[i]+=N[i-1];
        K[i]+=K[i-1];
        B[i]+=B[i-1];
    }
    ll O=((x[1]+x[2]+2*x[3])*l)/(x[0]+x[3]);
    int las=tot-1; 
    for(;N[las]==n;las--);
    ll ans=-inf;
    int left_t=0,right_t=-1;
    memset(left_i,0x3f,sizeof(left_i));
    for(int i=1;i<tot;i++){
        while(right_t+1<i&&right_t+1<=las){
            right_t++;
            left_i[right_t]=i;
        }
        while(left_t<L[i-1]){
            right_i[left_t]=i-1;
            left_t++;
        }
    }
    while(left_t<=right_t)
        right_i[left_t]=tot-1,left_t++;
    S1.init(tot);
    if(left_i[0]<=right_i[0])
        S1.add(left_i[0],right_i[0],K[0],dp[0]-B[0]-x[3]*t[0],0,tot-1,1);
    for(int i=1;i<tot;i++){
        dp[i]=max(S1.ask(i,0,tot-1,1)+B[i]-K[i]*t[i]+x[3]*t[i]-(x[1]+x[2]+2*x[3])*l,
                  dp[i-1]+B[i]-B[i-1]-(K[i]-K[i-1])*t[i]-x[0]*(t[i]-t[i-1]));
        if(left_i[i]<=right_i[i])
            S1.add(left_i[i],right_i[i],K[i],dp[i]-B[i]-x[3]*t[i],0,tot-1,1);
        if(N[i]==n)ans=max(ans,dp[i]);
    }
    cout<<ans;
    return 0;
}

标签:20241016,快速访问,int,ll,mxn,dep,maxn,define,门童
From: https://www.cnblogs.com/nagato--yuki/p/18470439

相关文章

  • 20241016下午
    P1040启发式图染色问题(color)我们可以先想一棵树的情况,如下图所示但是显然这个节点数量是\(2^k\),我们可以考虑二分图,然后你推着推着就会发现一个建图方案具体来说,我们可以现在左边创建一个颜色为\(1\)的结点,然后我们想让颜色数量尽量多,我们直接在右边创建一个颜色......
  • 20241016
    intarr[3]={10,20,30};int*parr=arr;1.*parr、*arr分别代表什么   *(parr+0)==*(arr+0)==10==》取首素值=========================================================================      2.*(parr+1)、*(arr+1)、*parr+1、*arr+1分别......
  • 20241016每日一题洛谷P1115
    普及-洛谷P1115最大子段和读题可知需要在一段一维数组中寻找一段唯一的区间,使区间内的数和最大,即寻找和最大区间可以想到前缀和的算法假设输入数组a[n]则前缀和数组b[n]=b[n-1]+a[n]那么从什么时候开始的一段区间才能使区间内的数和最大?从前缀和数组逐步来判断这一条......
  • 20241016 模板清理
    区间DP-回文字串记\(f[i][j]\)表示把\(s[i\simj]\)变成回文,最少补几个,从\(f[i][j-1],f[i+1][j],f[i+1][j-1]\)三种情况转移过来即可。感性理解一下这样的状态定义是有最优子结构的。区间DP-合唱队肯定可以区间\(dp\),再注意到状态的转移和上一步有关,所......
  • [20241016]Oracle C functions annotations补充.txt
    [20241016]OracleCfunctionsannotations补充.txt--//网站orafun.info可以查询oraclecfunctions.CreatedbyFritsHooglandwithalittlehelpfromKamilStawiarski.--//可以通过它了解oracle内部C函数.实际上可以直接下载相关文件,在本地使用.https://gitlab.com/Frits......
  • 20241016 模拟赛总结
    期望得分:100+100+55(?)+0=255实际得分:100+100+0+0=200迷迷糊糊睡了好一会才起来打……感觉打的还行,除了T3时间太紧了,有的错误没检查出来挂分了。。T1简单线性DP。\(f_i\)表示前i个数的答案,\(g_i\)有点抽象,先假设当前在\(p\),\(a_p=i\),\(g_i\)表示的是如果\(p\)......
  • 使用@lakehouse-rs/flight-sql-client nodejs api 快速访问dremio 服务
    @lakehouse-rs/flight-sql-client是基于rust开发的nodearrowflightsqlclient,dremio目前也是推荐基于arrowflightsql的访问模式参考代码package.json{"name":"node-arrow-flight-sql","version":"1.0.0","ma......
  • 善用AI:智能写作与快速访问的双重优势(附镜像站汇总)
    随着人工智能技术的不断发展,我们的日常工作和学习方式正在经历一场革命。在众多创新工具中,GPT(GenerativePre-trainedTransformer)已经成为了一个耀眼的明星,而这个月Claude3的登场,再次将人工智能推向新一轮高峰。为什么要使用AI? 提高效率GPT、Claude等,作为先进的自然语言......
  • 固定常用文件夹到快速访问
    对windows系列系统,就是日常的效率工具,总有一些很常用,每每见过,似曾相识,又每每不得其法的小技巧,因不是主业,影响有亦可以忽略,少有深究的。win窗口左侧有一个快速访问栏,用来打开常用的文件夹很便捷,印象中好像拖文件夹过去就可以了,有每每实现不了,好像偶尔又莫名其妙的可以了的操作,就这......
  • 出海业务如何搭建国内也能快速访问的https网站与接口(无需备案)
    背景信息由于最近在搭建我的出海网站https://www.idatariver.com/zh-cn,感兴趣的可以看看。其中一个环节便是给后端API接口加上ssl,毕竟http看着不如https,但因为没有备案,所以不能使用国内的服务器(国内未备案域名是不开放服务器443和80端口的),本文便是解决怎么在网站没有备案的......