noip模拟70[挺好]

noip模拟70 solutions

赛时排行榜好像还是挺好看的

嘿嘿,我还有一小会是第一呢,原因是人家的码还没有评测

然而我改题一点都改不动,一整个下午就一道题都没有调出来

除了我考场上切掉的那个题,就直接啥也不会

全是拍的

T1 暴雨

这个???拍的

大概意思好像是,先按照高度从大到小排序,然后向序列中一个一个的插入

这样我每次插入,就可以维护此时的奇偶性

至于你这数组如何开出来,因为你最多删掉25个所以最多有二十多个端点

AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#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=25005;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,ans;
int a[N],p[N],jc[N];
int ys1[N],ny1,ys2[N],ny2;
int c1[30],n1,c2[30],n2,c3[30],n3,c4[30],n4;
int dp[2][27][27][27];
bool comp(int x,int y){return a[x]>a[y];}
void get(int &x){x=(x%mod+mod)%mod;}
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=1ll*ret*x%mod;
        x=1ll*x*x%mod;y>>=1;
    }return ret;
}
int C(int x,int y){return 1ll*jc[x]*ksm(1ll*jc[x-y]*jc[y]%mod,mod-2)%mod;}
signed main(){
    #ifdef oj
        freopen("rain.in","r",stdin);
        freopen("rain.out","w",stdout);
    #endif
    scanf("%d%d",&n,&m);
    //n=read();m=read();
    fo(i,1,n)scanf("%d",&a[i]),p[i]=i;
    sort(p+1,p+n+1,comp);int now=0;
    fo(i,1,n){now^=1;
        memcpy(c3,c1,sizeof(c1));memcpy(c4,c2,sizeof(c2));n3=n1;n4=n2;
        int h=p[i];c1[++n1]=h;c2[++n2]=h;
        sort(c1+1,c1+n1+1);sort(c2+1,c2+n2+1,greater<int>());
        n1=min(n1,m+1);n2=min(n2,m+1);
        fo(j,1,n1)ys1[c1[j]]=j;
        fo(j,1,n2)ys2[c2[j]]=j;
        //cout<<"sb"<<i<<endl;
        fo(l,1,n3)fo(r,1,n4)fo(k,0,m){
            //cout<<"SB"<<endl;
            if(dp[now^1][l][r][k]){
            int x=c3[l],y=c4[r],v=dp[now^1][l][r][k];dp[now^1][l][r][k]=0;
            //cout<<i<<" "<<l<<" "<<r<<" "<<v<<endl;
            if(h<x){
                if(((x-h-1)&a[h])&1)(dp[now][ys1[h]][ys2[y]][k]+=mod-v)%=mod;
                else (dp[now][ys1[h]][ys2[y]][k]+=v)%=mod;
            }
            else if(h>y){
                if(((h-y-1)&a[h])&1)(dp[now][ys1[x]][ys2[h]][k]+=mod-v)%=mod;
                else (dp[now][ys1[x]][ys2[h]][k]+=v)%=mod;
                //cout<<"this"<<" "<<(((h-y-1)&a[h])&1)<<" "<<v<<endl;
            }
            else {
                if(a[h]&1)(dp[now][ys1[x]][ys2[y]][k]+=mod-v)%=mod;
                else (dp[now][ys1[x]][ys2[y]][k]+=v)%=mod;
            }
            if(k)(dp[now][ys1[x]][ys2[y]][k-1]+=v)%=mod;
        }
        }
        if(i-1<=m)(dp[now][ys1[h]][ys2[h]][m-i+1]+=1)%=mod;
    }
    fo(i,1,n1)fo(j,1,n2)ans=(ans+dp[now][i][j][0])%mod;//cout<<dp[now][i][j][0]<<" ";cout<<endl;
    jc[0]=1;fo(i,1,n)jc[i]=1ll*jc[i-1]*i%mod;
    int tot=C(n,m);//cout<<ans<<" "<<tot<<endl;
    ans=(1ll*(1ll*tot+ans%mod+mod)*ksm(2,mod-2)%mod+mod)%mod;
    printf("%d",ans);
}

T2 AVL树

这个就是我调了一下午但是啥结果都没有的题???

不知道是我能力不足还是咋地

我之前一直认为没有我认真调然后调不出来的题!!

但是这两天的题给我干傻了,真\(TM\)不会

原因是我一直只考虑了左子树深度对右子树的影响,并没有考虑原树的形态

可能之前一个大分叉,保证右边那颗子树深度必须大于某些东西

但是在右子树内,她的左子树深度不够,必须要用右子树,我没考虑这个

所以只需要记录一下,一直下放就好了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#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=5e5+5;
int n,k;
int rt,p[N],ls[N],rs[N];
queue<int> q;
int vis[N];
int f[N],dep[N],mxd[N];
int h[N],lh[N];
void dfs(int x){
    dep[x]=dep[p[x]]+1;mxd[x]=dep[x];
    if(ls[x])dfs(ls[x]),mxd[x]=max(mxd[x],mxd[ls[x]]);
    if(rs[x])dfs(rs[x]),mxd[x]=max(mxd[x],mxd[rs[x]]);
}
bool chk(int x){
    int ret=0,now=max(dep[x],h[x]);
    //cout<<x<<endl;
    while(~x){
        if(!vis[x])ret++;
        now=max(now,h[x]);
        if(x<p[x])ret+=f[max(now-1,lh[rs[p[x]]])-dep[p[x]]];
        x=p[x];
    }
    //cout<<x<<" "<<ret<<" "<<k<<endl;
    return ret<=k;
}
void tag(int x){
    h[x]=max(h[x],dep[x]);
    int now=h[x];
    while(~x){
        h[x]=max(h[x],now);
        if(!vis[x])vis[x]=1,k--;
        if(x<p[x]&&rs[p[x]])lh[rs[p[x]]]=max(lh[rs[p[x]]],h[x]-1);
        x=p[x];
    }
}
void sol(int x){
    if(chk(x))tag(x);
    if(ls[x]&&rs[x]){
        if(mxd[ls[x]]<lh[x])lh[rs[x]]=max(lh[rs[x]],lh[x]),lh[ls[x]]=max(lh[ls[x]],lh[x]-1);
        else lh[ls[x]]=max(lh[ls[x]],lh[x]),lh[rs[x]]=max(lh[rs[x]],lh[x]-1);
        sol(ls[x]);sol(rs[x]);
    }
    else {
        if(ls[x])lh[ls[x]]=max(lh[ls[x]],lh[x]),sol(ls[x]);
        if(rs[x])lh[rs[x]]=max(lh[rs[x]],lh[x]),sol(rs[x]);
    }
}
signed main(){
    #ifdef oj
        freopen("avl.in","r",stdin);
        freopen("avl.out","w",stdout);
    #endif
    scanf("%d%d",&n,&k);
    fo(i,1,n){
        scanf("%d",&p[i]);
        if(p[i]==-1){rt=i;continue;}
        if(i<p[i])ls[p[i]]=i;
        else rs[p[i]]=i;
    }
    f[1]=1;fo(i,2,40)f[i]=f[i-1]+f[i-2]+1;
    dfs(rt);sol(rt);fo(i,1,n)printf("%d",vis[i]);
}

T3 挖掘机

一看就是一层一层的消掉

一般这样的题的处理方式就是倍增

AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#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 H=15;
const int W=1e5+5;
const int K=1e5+5;
int h,w,k,Q;
int jz[H][W];
int st[H][W][19];
int fir[H][W];
signed main(){
    #ifdef oj
        freopen("blueshit.in","r",stdin);
        freopen("blueshit.out","w",stdout);
    #endif
    scanf("%d%d%d%d",&h,&w,&k,&Q);
    memset(st,0x3f,sizeof(st));
    memset(fir,0x3f,sizeof(fir));
    fo(i,1,h){
        char s[W];
        scanf("%s",s+1);
        fo(j,1,w){
            if(s[j]=='X')jz[i][j]=1;
            else jz[i][j]=0;
        }
        fu(j,w,1){
            if(jz[i][j])fir[i][j]=j;
            else fir[i][j]=fir[i][j+1];
            if(jz[i][j])st[i][j][0]=fir[i][j+k];
            else if(fir[i][j]<=w)st[i][j][0]=st[i][fir[i][j]][0];
            for(int o=1;o<=18&&st[i][j][o-1]<=w;o++)st[i][j][o]=st[i][st[i][j][o-1]][o-1];
        }
    }
    //cout<<"sb"<<" "<<fir[1][9]<<endl;
    while(Q--){
        int d,l,r;scanf("%d%d%d",&d,&l,&r);
        int ans=0;
        fo(i,1,d){
            int now=l,res=0;
            fu(j,18,0)if(st[i][now][j]<=r){
                res+=(1<<j);
                //cout<<i<<" "<<now<<" "<<j<<" "<<st[i][now][j]<<endl;
                now=st[i][now][j];
            }
            if(!res&&fir[i][l]>r)res=0;
            else res++;
            ans+=res;//cout<<res<<endl;
        }
        printf("%d\n",ans);
    }
}

T4 不会

posted @ 2021-10-07 21:05  fengwu2005  阅读(98)  评论(0编辑  收藏  举报