zoukankan      html  css  js  c++  java
  • 8.9模拟赛

    A组

    T1.dostavljac 餐馆

    树形DP,怎么处理走回来呢?考场想了f[i][j][0/1]表示以i为根子树,用了j秒,并且选/不选当前点,不能转移,为什么呢?因为这个第三维完全没用,可以在一开始就考虑。

    正解f[i][j][0/1]表示以i为根的子树,用了j秒,并且回到/不回到当前点,这样就可以分类转移了。

    转移时考虑做到子树v,分三类讨论。

    注意一个点只能选一次,倒序循环。

    #include<iostream>
    #include<cstdio>
    
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=1005;
    
    struct Edge{
        int next,to;
    }e[MAXN];
    int ecnt,head[MAXN],ind[MAXN];
    inline void add(int x,int y){
        e[++ecnt].next = head[x];
        e[ecnt].to = y;
        head[x] = ecnt;
    }
    
    int n,m;
    
    int f[MAXN][MAXN*2][2];
    int a[MAXN];
    
    int ans=0;
     
    
    void dfs(int x,int pre){
        f[x][1][0]=f[x][1][1]=a[x];
        int tmp=0,mx=0;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(v==pre) continue;
            dfs(v,x);
            for(int j=m;j>=0;j--){
                for(int k=m-j-1;k>=0;k--){
                    f[x][j+k+2][0]=max(f[x][j+k+2][0],f[x][j][0]+f[v][k][0]);
                    f[x][j+k+2][1]=max(f[x][j+k+2][1],f[x][j][1]+f[v][k][0]);
                    f[x][j+k+1][1]=max(f[x][j+k+1][1],f[x][j][0]+f[v][k][1]);
                }
            }
        }
    }
    
    void solve(){
        dfs(1,0);
        cout<<max(f[1][m][1],f[1][m][0]);
    }
    
    int main(){
        freopen("dostavljac.in","r",stdin);
        freopen("dostavljac.out","w",stdout);
        n=rd();m=rd();
        int x,y;
        for(int i=1;i<=n;i++) a[i]=rd();
        for(int i=1;i<=n-1;i++){
            x=rd();y=rd();
            add(x,y);add(y,x);
        }
        solve();
        return 0;
    }
    View Code

     T2.range 区间

    分块维护块内前缀后缀积,块大小为k正好满足。

    被一般套路限制了,这个分块不需要真的开新数组存,那样空间是n^2的(用vector可以少一些,但依旧很大)

    正解是直接在原位置上维护这个位置在块内的前缀后缀,这样就可以啦。

    这题卡空间(差评)

    #include<iostream>
    #include<cstdio>
    #include<vector>
    //#define int long long
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=20000005;
    
    int n,m,mod;
    int A,B,C,D;
    int a[MAXN];
    
    int num;
    int pre[MAXN],lst[MAXN];
    
    #define l(x) ((((x)-1)*m)+1)
    #define r(x) ((x)==num?n:((x)*m))
    #define bl(x) ((((x)-1)/m)+1)
    
    signed main(){
        freopen("range.in","r",stdin);
        freopen("range.out","w",stdout);
        n=rd();m=rd();mod=rd();
        A=rd();B=rd();C=rd();D=rd();
        a[1]=A;
        long long tmp;
        for(int i=2;i<=n;i++) {
            tmp=1ll*(a[i-1]*1ll*B+C)%D;
            a[i]=(int) tmp; 
        }
        num=n/m;if(n%m)num++;
        
        for(int i=1;i<=num;i++){
            int L=l(i),R=r(i);
            pre[L]=a[L];
            for(int j=L+1;j<=R;j++){
                tmp=(pre[j-1]*1ll*a[j])%mod;
                pre[j]=(int)tmp;
            }
            lst[R]=a[R];
            for(int j=R-1;j>=L;j--){
                tmp=1ll*(lst[j+1]*1ll*a[j])%mod;
                lst[j]=(int)tmp;
            }
        }
        int ans=0;
        for(int i=1;i<=n-m+1;i++){
            int j=i+m-1;
            if(bl(i)==bl(j)){ans^=pre[r(bl(i))];continue;}
            tmp=1ll*(lst[i]*1ll*pre[j])%mod;
            ans^=(int)tmp;
        }
        cout<<ans;
        return 0;
    }
    View Code

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9451654.html

  • 相关阅读:
    C语言字母频率统计
    C语言文件操作相关函数
    【蓝桥杯】历届试题 回文数字
    【蓝桥杯】历届试题 蚂蚁感冒
    【蓝桥杯】历届试题 地宫取宝
    【蓝桥杯】历届试题 分糖果
    【蓝桥杯】历届试题 兰顿蚂蚁
    JDK的安装和配置
    【蓝桥杯】历届试题 错误票据
    【蓝桥杯】历届试题 带分数
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9451654.html
Copyright © 2011-2022 走看看