zoukankan      html  css  js  c++  java
  • 20190811 NOIP模拟测试17 「入阵曲 · 将军令 · 星空 」

    T1 入阵曲

      将二维压成一维来做,维护每一列的前缀和,n^2枚举最上一行和最下一行,把中间这几行当成一行来做,维护一个桶记录这几行前几列的和的余数是x的个数,因为在模K意义下余数相同的两个数的差是K的倍数 时间复杂度 O(n^3)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,K,a[410][410],sum[410][410],tmp[1100000],p[1100000];
    inline int read(){
        register int ret;
        register char r;
        while(r=getchar(),r<'0'||r>'9');
        ret=r^48;
        while(r=getchar(),r>='0'&&r<='9') ret=(ret<<1)+(ret<<3)+(r^48);
        return ret;
    }
    int main(){
        n=read(),m=read(),K=read();
        for(register int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                a[i][j]=read(),
                sum[i][j]=(sum[i-1][j]+a[i][j])%K;//维护第j列前缀和
        long long ans=0;
        for(register int i=1;i<=n;i++){
            for(register int j=i;j<=n;j++){
                int cet=0;
                for(register int l=1;l<=m;l++){
                    cet=((cet+sum[j][l]-sum[i-1][l])%K+K)%K;
                    ans+=tmp[cet]++;
                    if(cet==0) ans++;
                    if(tmp[cet]==1) p[++p[0]]=cet;
                }
                for(int l=1;l<=p[0];l++) tmp[p[l]]=0;
                p[0]=0;
            }
        }
        printf("%lld
    ",ans);
    }
    View Code

    T2 将军令

      可以想到像 小胖守皇宫 那样的树上DP ,k==1的情况可以做,k==2的情况也可以YY掉,但是K==3或20的情况就不好YY了(但是听说洛谷上有写DP 通式的,码量很小)

      正解是贪心,无根树变有根树,DFS 一遍,用大根堆维护深度最深的点,从该点向上找距他为K的点(如果距离小于K就走到了根,那就用根就行了),然后从这个点在整棵树上找距他小于等于K的点,以后从堆里拿出标记的点直接跳即可。 注意在标记的时候,千万不要碰到一个标记过的点就return,有可能这个点的儿子没有被覆盖,而当前驻扎小队的点会覆盖它的儿子

      PS :这样会TLE 95 ,可以记录如果一个点的所有子孙都被覆盖了(标记过),在开一个数组,把该点标记,这种点是可以跳的

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int n,d,t,tot;
    int to[210000],head[110000],nex[210000],fa[210000],v[210000],al[210000];
    struct node{
        int dep,id;
        bool operator < (node b)const{
            return dep<b.dep;
        }
        node(int a,int b){id=a,dep=b;}
    };
    priority_queue<node>q;
    void add(int x,int y){
        to[++tot]=y,nex[tot]=head[x],head[x]=tot;
    }
    void dfs(int x,int pre,int dis){
        q.push(node(x,dis+1));
        fa[x]=pre;
        for(int i=head[x];i;i=nex[i]){
            int y=to[i];
            if(y==pre) continue;
            dfs(y,x,dis+1);
        }
    }
    void work(int x,int k){
        v[x]=1;
        if(nex[head[x]]==0){
            if(to[head[x]]==fa[x]||al[to[head[x]]]) al[x]=1;
        }
        if(k==0) return;
        for(int i=head[x];i;i=nex[i]){
            int y=to[i];
            if(al[y]) continue;//避免重复,陷入死循环
            work(y,k-1);//走儿子的同时,也能走到爸爸
        }
        for(int i=head[x];i;i=nex[i]){
            int y=to[i];
            if(y==fa[x]) continue;
            al[x]=min(al[y],al[x]);
        }
    }
    int main(){
        scanf("%d%d%d",&n,&d,&t);
        for(int i=1,x,y;i<n;i++){
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs(1,0,0);
        int ans=0;
        while(q.size()){
            int w=q.top().id;
            q.pop();
            if(v[w]) continue;
            for(int i=1;i<=d&&w!=1;i++,w=fa[w]);
            ans++;
            work(w,d);
        }
        printf("%d
    ",ans);
    }
    View Code

    T3 星空

       https://www.luogu.org/problemnew/solution/P3943

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    int n,K,m,num;
    int a[41000],b[70],c[20],v[41000],dis[20][41000],inq[41000],f[1<<17],to[1<<17];
    void Dijistra(){
        memset(dis,0x3f,sizeof(dis));
        queue<int>q;
        for(int w=1;w<=num;w++){
            q.push(c[w]);
            inq[c[w]]=1;
            dis[w][c[w]]=0;
            while(q.size()){
                int x=q.front();
                inq[x]=0;
                q.pop();
                for(int i=1;i<=m;i++){
                    int y=x-b[i];
                    if(y>0&&dis[w][y]>dis[w][x]+1){
                        dis[w][y]=dis[w][x]+1;
                        if(!inq[y]){
                            q.push(y);
                            inq[y]=1;
                        }
                    }
                    y=x+b[i];
                    if(y<=n&&dis[w][y]>dis[w][x]+1){
                        dis[w][y]=dis[w][x]+1;
                        if(!inq[y]){
                            q.push(y);
                            inq[y]=1;
                        }
                    }
                }
            }
        }
    }
    int main(){
        scanf("%d%d%d",&n,&K,&m);
        n++;
        for(int i=1,x;i<=K;i++){
            scanf("%d",&x);
            a[x]^=1,a[x+1]^=1;
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&b[i]);
        }
        for(int i=1;i<=n;i++){
            if(a[i])
                 c[++num]=i;
        }
        Dijistra();
    /*    cout<<num<<endl;
        for(int i=1;i<=num;i++){
            for(int j=1;j<=num;j++){
                printf("%d %d %d
    ",i,j,dis[i][c[j]]);
            }
        }*/
        memset(f,0x3f,sizeof(f));
        f[0]=0;
        for(int i=1;i<=num;i++) to[1<<(i-1)]=i;
        for(int i=0;i<=(1<<num)-1;i++){
            for(int j=i;j;j-=j&(-j)){
                int w=to[j&(-j)],sta=j-(j&(-j));
                for(int l=sta;l;l-=l&(-l)){
                    int ww=to[l&(-l)];
                    f[i]=min(f[i],f[i^(j&(-j))^(l&(-l))]+dis[w][c[ww]]);
                }
            }
        }
        printf("%d
    ",f[(1<<num)-1]);
    }
    View Code

        

  • 相关阅读:
    暑假周总结02
    音乐播放器
    setInterval、控制停止和继续
    暑假周总结01
    ul li、a标签的下划线
    innerHTML、document获取对象、className修改样式
    领扣(LeetCode)N叉树的层序遍历 个人题解
    领扣(LeetCode)两句话中的不常见单词 个人题解
    领扣(LeetCode)二叉树的中序遍历 个人题解
    领扣(LeetCode)用队列实现栈 个人题解
  • 原文地址:https://www.cnblogs.com/heoitys/p/11336760.html
Copyright © 2011-2022 走看看