noip模拟56[落寞]

noip模拟56 solutions

忘了啥感觉了,好像考得不咋地。。。。

T1 爆零

原题直接dp,然后我是\(\mathcal{O(nlogn)}\)

AC_code
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
#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 n,fa[N];
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 dep[N],mxd[N];
void dfs_pre(int x,int d){
    dep[x]=d;mxd[x]=dep[x];
    for(int i=head[x],y;i;i=nxt[i]){
        y=to[i];dfs_pre(y,d+1);
        mxd[x]=max(mxd[x],mxd[y]);
    }
}
struct node{
    int who,mxn;
    node(){}
    node(int x,int y){who=x;mxn=y;}
    bool operator < (node a)const{return mxn<a.mxn;}
};
vector<node> vec[N];
int sum[N],ans[N];
void dfs_ans(int x){
    if(!head[x]){sum[x]=1;return ;}
    for(int i=head[x],y;i;i=nxt[i]){
        y=to[i];dfs_ans(y);
        vec[x].push_back(node(y,mxd[y]));
        ans[x]+=sum[y];
    }
    sort(vec[x].begin(),vec[x].end());
    fo(i,0,vec[x].size()-1){
        if(i&&vec[x][i-1].mxn-dep[x]<dep[x])sum[x]--,ans[x]+=vec[x][i-1].mxn-dep[x];
        sum[x]+=sum[vec[x][i].who];ans[x]+=ans[vec[x][i].who];
    }
}
signed main(){
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d",&n);
    fo(i,2,n)scanf("%d",&fa[i]),add_edg(fa[i],i);
    dfs_pre(1,1);dfs_ans(1);
    printf("%d",ans[1]);
}

T2 底垫

考场上只会\(\mathcal{O(n^2logn)}\)的做法

所以我只拿了45pts,不对,我数组开小了所以拿了20pts

正解是珂朵莉树,用set拆分区间,然后用后缀的树状数组维护

因为你维护的是对于每一个右端点来说的左端点,从后往前走

主要是找好式子,就按照官方上的那个式子拆开就好了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
#define int long long
const int N=2e5+5;
const int mod=1e9+7;
int n,m,ans[N];
struct QUS{
    int l,r,id;QUS(){}
    bool operator < (QUS x)const{return r<x.r;}
}qus[N];
struct dream{
    int l,r,t;dream(){}
}sca[N];
struct BIT{
    int sum[N];
    BIT(){}
    void ins(int x,int v){for(int i=x;i;i-=i&(-i))(sum[i]+=v)%=mod;}
    int get(int x){int ret=0;for(int i=x;i<=n;i+=i&(-i))(ret+=sum[i])%=mod;return ret;}
}ql,qr,qlr,qc;
struct kdl{
    int l,r,t;kdl(){}
    kdl(int x,int y,int z){l=x;r=y;t=z;}
    bool operator < (kdl x)const{return l<x.l;}
};
set<kdl> st;
set<kdl>::iterator spilt(int x){
    set<kdl>::iterator it=st.lower_bound(kdl(x,0,-1));
    if(it->l==x)return it;
    it=prev(it);int l=it->l,r=it->r,t=it->t;
    st.erase(it);st.insert(kdl(l,x-1,t));
    return st.insert(kdl(x,r,t)).first;
}
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;
}
void sol(int x){
    set<kdl>::iterator beh=spilt(sca[x].r+1);
    set<kdl>::iterator fro=spilt(sca[x].l);
    while(fro!=beh){
        int k=fro->r-fro->l+1,ft=fro->t,jus;
        ql.ins(sca[x].t,jus=k*(sca[x].t-1)%mod);
        ql.ins(ft,(mod-jus)%mod);

        qr.ins(sca[x].t,jus=k*(sca[x].t+1)%mod);
        qr.ins(ft,(mod-jus)%mod);
        qr.ins(ft,k*(sca[x].t+mod-ft)%mod);
        
        qlr.ins(sca[x].t,jus=(mod-k)%mod);
        qlr.ins(ft,(mod-jus)%mod);
        
        qc.ins(sca[x].t,jus=k*(mod+1-sca[x].t*sca[x].t%mod)%mod);
        qc.ins(ft,(mod-jus)%mod);
        qc.ins(ft,k*(sca[x].t*ft%mod+mod-ft%mod-sca[x].t*sca[x].t%mod+mod+sca[x].t)%mod);
        fro=next(fro);st.erase(prev(fro));
    }
    st.insert(kdl(sca[x].l,sca[x].r,sca[x].t));
    return ;
}
signed main(){
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    fo(i,1,n)scanf("%lld%lld",&sca[i].l,&sca[i].r),sca[i].t=i,sca[i].r--;
    fo(i,1,m)scanf("%lld%lld",&qus[i].l,&qus[i].r),qus[i].id=i;
    sort(qus+1,qus+m+1);int it=0;
    st.insert(kdl(0,1e9,0));
    fo(i,1,m){
        int fz=0,fm=(qus[i].r-qus[i].l+1)*(qus[i].r-qus[i].l+2)/2%mod;
        while(it<qus[i].r)it++,sol(it);
        fz=(fz+qus[i].l*ql.get(qus[i].l))%mod;
        fz=(fz+qus[i].r*qr.get(qus[i].l))%mod;
        fz=(fz+qus[i].l*qus[i].r%mod*qlr.get(qus[i].l))%mod;
        fz=(fz+qc.get(qus[i].l))%mod;
        ans[qus[i].id]=fz*ksm(fm,mod-2)%mod;
    }
    fo(i,1,n)printf("%lld\n",ans[i]);
}

T3 高考

首先证明所有情况是等概率的,注意这里指的是不排序的情况

然后直接递归回去

AC_code
#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=5005;
const int mod=1e9+7;
int n,m;
int jc[N*2],inv[N*2],nc[N*2];
int g[N][N],f[N][N],ans[N];
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;
}
int C(int x,int y){return jc[x]*inv[y]%mod*inv[x-y]%mod;}
signed main(){
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    jc[0]=1;fo(i,1,n+m)jc[i]=jc[i-1]*i%mod;
    inv[0]=1;inv[n+m]=ksm(jc[n+m],mod-2);
    fu(i,n+m-1,1)inv[i]=inv[i+1]*(i+1)%mod;
    nc[0]=1;fo(i,1,n+m)nc[i]=nc[i-1]*n%mod;
    fo(i,1,n)fo(j,1,m/i){
            int bas=1;
            fo(k,i,m/j)g[i][j]=(g[i][j]+bas*C(k,i)*C(n,k)%mod*C(m+n-1-j*k,n-1)%mod+mod)%mod,bas=-bas;
        }
    fo(j,1,m)fu(i,m/j,1)f[i][j]=(f[i+1][j]+g[i][j])%mod;
    fo(i,1,n){
        fo(j,1,m/i)ans[i]=(ans[i]+f[i][j])%mod;
        ans[i]=(ans[i]+ans[i-1])%mod;
        printf("%lld\n",(ans[i]*ksm(C(n+m-1,n-1),mod-2)+i)%mod);
    }
}
posted @ 2021-09-19 16:10  fengwu2005  阅读(36)  评论(0编辑  收藏  举报