多校冲刺 noip 11.11

多校冲刺 noip 11.11

所以我再一次对着最后一个题调了两个小时??!!

T1 嗑瓜子

智障概率\(DP\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    char ch=getchar();int f=1,s=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return f*s;
}
const int N=2e3+5;
const int mod=998244353;
int n,ans,dp[2][N*2],f[2][N*2],inv[N*5],tmp;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
signed main(){
    freopen("eat.in","r",stdin);
    freopen("eat.out","w",stdout);
    n=read();inv[0]=inv[1]=1;
    fo(i,2,3*n)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    int now=0;f[now][0]=1;
    fu(i,n,1){
        fo(j,0,2*n)dp[now^1][j]=0,f[now^1][j]=0;
        fu(j,2*(n-i),0){
            tmp=(dp[now][j]+f[now][j])*inv[i+j]%mod;
            if(i){
                dp[now^1][j+2]=(dp[now^1][j+2]+tmp*i)%mod;
                f[now^1][j+2]=(f[now^1][j+2]+f[now][j]*inv[i+j]%mod*i)%mod;
            }
            if(j){
                dp[now][j-1]=(dp[now][j-1]+tmp*j)%mod;
                f[now][j-1]=(f[now][j-1]+f[now][j]*inv[i+j]%mod*j)%mod;
            }
        }
        now^=1;
    }
    fo(i,0,2*n)ans=(ans+dp[now][i])%mod;//cout<<i<<" "<<dp[0][i]<<endl;
    printf("%lld",ans);
    return 0;
}

T2 第k大查询

所以这个是我一不小心想出来的??

直接找到左右比他大的每一个坐标

这个可以用链表维护

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    char ch=getchar();int f=1,s=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return f*s;
}
const int N=5e5+5;
int n,k,a[N],ans,pos[N];
int pre[N],beh[N];
int sta[N],top;
int le[60],ri[60],cle,cri;
signed main(){
    freopen("kth.in","r",stdin);
    freopen("kth.out","w",stdout);
    // cerr<<(sizeof(a)*5>>20)<<endl;
    n=read();k=read();
    fo(i,1,n)a[i]=read(),pos[a[i]]=i;
    fo(i,1,n)pre[i]=i-1,beh[i]=i+1;
    fo(i,1,n){
        int x=pos[i],now;cle=cri=0;le[0]=ri[0]=x;
        now=x;while(pre[now]&&cle<k)le[++cle]=pre[now],now=pre[now];le[cle+1]=0;
        now=x;while(beh[now]!=n+1&&cri<k)ri[++cri]=beh[now],now=beh[now];ri[cri+1]=n+1;
        fo(l,max(k-1-cri,0ll),min(cle,k-1)){
            int r=k-1-l;
            ans+=i*(le[l]-le[l+1])*(ri[r+1]-ri[r]);
        }
        if(pre[x])beh[pre[x]]=beh[x];
        if(beh[x]!=n+1)pre[beh[x]]=pre[x];
    }
    printf("%lld",ans);
    return 0;
}

T3 树上路径

直接两边都\(DP\)一遍,统计答案就好了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    char ch=getchar();int f=1,s=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return f*s;
}
const int N=5e5+5;
int n;ll ans;
int to[N*2],nxt[N*2],head[N],rp;
void add_edg(int x,int y){
    to[++rp]=y;
    nxt[rp]=head[x];
    head[x]=rp;
}
int zj[N],s,t,len,dep[N];
bool ifzj[N];
int f[N],mxf[N],g[N],mxg[N];
int an[N],res;
void dfs_dep(int x,int fa){
    dep[x]=dep[fa]+1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa)continue;
        dfs_dep(y,x);
    }
}
void dfs_fzj(int x,int fa){
    //cout<<x<<" "<<fa<<endl;
    if(x==t)ifzj[x]=true;
    dep[x]=dep[fa]+1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa)continue;
        dfs_fzj(y,x);
        ifzj[x]=ifzj[x]|ifzj[y];
    }
    if(ifzj[x])zj[dep[x]]=x;
}
void dfs_f(int x,int fa){
    f[x]=1;mxf[x]=1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa)continue;
        dfs_f(y,x);
        f[x]=max(f[x],max(f[y],mxf[x]+mxf[y]));
        mxf[x]=max(mxf[x],mxf[y]+1);
    }
}
void dfs_g(int x,int fa){
    g[x]=1;mxg[x]=1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa)continue;
        dfs_g(y,x);
        g[x]=max(g[x],max(g[y],mxg[x]+mxg[y]));
        mxg[x]=max(mxg[x],mxg[y]+1);
    }
}
struct BIT{
    int tr[N];
    void ins(int x,int v){
        for(int i=x;i;i-=(i&-i))tr[i]=max(tr[i],v);
    }
    int query(int x){
        int ret=0;
        for(int i=x;i<=len;i+=(i&-i))ret=max(ret,tr[i]);
        return ret;
    }
}bit;
signed main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    n=read();
    fo(i,1,n-1){
        int x,y;x=read();y=read();
        add_edg(x,y);add_edg(y,x);
    }
    dfs_dep(1,0);
    fo(i,1,n)if(dep[i]>dep[s])s=i;
    dfs_dep(s,0);
    fo(i,1,n)if(dep[i]>dep[t])t=i;
    len=dep[t];dfs_fzj(s,0);
    //cout<<s<<" "<<t<<endl;
    dfs_f(s,0);dfs_g(t,0);
    //fo(i,1,n)cout<<i<<" "<<f[i]<<" "<<g[i]<<endl;
    fo(i,1,n)if(!ifzj[i])res=max(res,f[i]);
    bit.ins(len,res);bit.ins(res,len);
    fo(i,1,len-1){
        //cout<<zj[i]<<" "<<zj[i+1]<<endl;
        bit.ins(f[zj[i+1]],g[zj[i]]);
        bit.ins(g[zj[i]],f[zj[i+1]]);
    }
    fo(i,1,len)ans+=bit.query(i);//cerr<<i<<" "<<bit.query(i)<<endl;
    printf("%lld",ans);
    return 0;
}

T4 糖

贪心,官方题解挺好的

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=2e5+5;
const int C=1e6+5;
int n,c,a[N],buy[N],sel[N];
int st[N][20],lg[N];
int get_max(int l,int r){
    int t=lg[r-l+1];
    return max(st[l][t],st[r-(1<<t)+1][t]);
}
struct node{
    int sm,vl;
    node(){}
    node(int y,int z){sm=y;vl=z;}
}sta[N];
int hd=1,tl=0,ans;
signed main(){
    freopen("candy.in","r",stdin);
    freopen("candy.out","w",stdout);
    scanf("%lld%lld",&n,&c);
    fo(i,1,n)scanf("%lld",&a[i]);
    lg[0]=-1;fo(i,1,n)lg[i]=lg[i>>1]+1;
    fo(i,0,n-1)scanf("%lld%lld",&buy[i],&sel[i]);
    fo(i,0,n-1){
        int bg=0,sl=0,mst;
        if(i>0){
            mst=a[i]-a[i-1];
            int now=mst;
            while(hd<=tl&&sta[hd].sm<=now)now-=sta[hd].sm,hd++;
            sta[hd].sm-=now;
        }
        else mst=c;
        while(hd<=tl&&sta[tl].vl>=buy[i])
            bg+=sta[tl].sm,ans+=sta[tl].sm*sta[tl].vl,tl--;
        while(hd<=tl&&sta[hd].vl<=sel[i])
            sl+=sta[hd].sm,hd++;
        if(sl){hd--;sta[hd]=node(sl,sel[i]);}
        sta[++tl]=node(bg+mst,buy[i]);ans-=(bg+mst)*buy[i];
    }
    int now=a[n]-a[n-1];
    while(hd<=tl&&sta[hd].sm<=now)now-=sta[hd].sm,hd++;
    sta[hd].sm-=now;
    while(hd<=tl)ans+=sta[hd].sm*sta[hd].vl,hd++;
    printf("%lld",-ans);
}
posted @ 2021-11-11 19:11  fengwu2005  阅读(36)  评论(0)    收藏  举报