2021.11.17考试总结[冲刺NOIP模拟32]

T1 饥饿的狐狸

一大一小地贪心。

\(code:\)

T1
#include<bits/stdc++.h>
using namespace std;

namespace IO{
    #define int long long
    int read(){
        int x=0,f=0; 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 f?-x:x;
    } char Ch[50];
    void write(int x,char sp){
        int len=0;
        if(x<0) putchar('-'),x=-x;
        do{ Ch[len++]=x%10+'0'; x/=10; }while(x);
        for(int i=len-1;~i;i--) putchar(Ch[i]); putchar(sp);
    }
} using namespace IO;

const int NN=100010;
int n,w,mx,mn,zero,t[NN];
vector<int>obj,neg,tmp;

void solve_max(){
    for(int i=1;i<=zero;i++)
        obj.size()<neg.size()?obj.push_back(0):neg.push_back(0);
    int ext=min(obj.size(),neg.size()),reso=0,resn=0,sum=0;
    tmp=obj.size()<neg.size()?neg:obj;
    int l=ext,r=tmp.size()-1,lst=0;
    for(int i=0;i<ext;i++){
        reso+=abs(lst-obj[i]); lst=obj[i];
        reso+=abs(lst-neg[i]); lst=neg[i];
    }
    while(l<r){
        reso+=max(abs(lst-tmp[l]),abs(tmp[l])); lst=tmp[l];
        reso+=max(abs(lst-tmp[r]),abs(tmp[r])); lst=tmp[r];
        ++l; --r;
    }
    if(l==r) reso+=max(abs(lst-tmp[l]),abs(tmp[l]));
    lst=0; l=ext; r=tmp.size()-1;
    for(int i=0;i<ext;i++){
        resn+=abs(lst-neg[i]); lst=neg[i];
        resn+=abs(lst-obj[i]); lst=obj[i];
    }
    while(l<r){
        resn+=max(abs(lst-tmp[l]),abs(tmp[l])); lst=tmp[l];
        resn+=max(abs(lst-tmp[r]),abs(tmp[r])); lst=tmp[r];
        ++l; --r;
    }
    if(l==r) resn+=max(abs(lst-tmp[l]),abs(tmp[l]));
    mx=max(reso,resn);
}

signed main(){
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
    n=read(); w=read();
    for(int i=1;i<=n;i++){
        t[i]=read()-w;
        if(!t[i]) ++zero;
        else t[i]>0?obj.push_back(t[i]):neg.push_back(t[i]);
    }
    sort(obj.begin(),obj.end(),[](int a,int b)->bool{return a>b;});
    sort(neg.begin(),neg.end(),[](int a,int b)->bool{return a<b;});
    if(!neg.size()){
        for(int i=1;i<=zero;i++) obj.push_back(0);
        int l=0,r=obj.size()-1,lst=0;
        while(l<r){
            mx+=max(abs(lst-obj[l]),abs(obj[l])); lst=obj[l];
            mx+=max(abs(lst-obj[r]),abs(obj[r])); lst=obj[r];
            ++l; --r;
        }
        if(l==r) mx+=max(abs(lst-obj[l]),abs(obj[l]));
        mn=obj[0];
    } else if(!obj.size()){
        for(int i=1;i<=zero;i++) neg.push_back(0);
        int l=0,r=neg.size()-1,lst=0;
        while(l<r){
            mx+=max(abs(lst-neg[l]),abs(neg[l])); lst=neg[l];
            mx+=max(abs(lst-neg[r]),abs(neg[r])); lst=neg[r];
            ++l; --r;
        }
        if(l==r) mx+=max(abs(lst-neg[l]),abs(neg[l]));
        mn=-neg[0];
    } else{
        mn=obj[0]-neg[0];
        solve_max();
    }
    write(mn,' '); write(mx,'\n');
    return 0;
}

T2 保险箱

由裴蜀定理,设 \(c_i\) 为可行的位置,则有
\(a_1n+a_2c_1+a_3c_2+\ldots+a_ic_{i-1}+a_{i+1}m_k\)
在模 \(n\) 意义下最小取到 \(gcd(n,c_i,m_k)\) 。于是问题变成了求最小的 \(g\) ,使 \(\forall i\in[1,k),g\nmid m_i\) ,答案即为 \(\frac{n}{g}\)

于是暴力枚举(?

\(code:\)

T2
#include<bits/stdc++.h>
using namespace std;

namespace IO{
    #define int long long
    int read(){
        int x=0,f=0; 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 f?-x:x;
    } char Ch[50];
    void write(int x,char sp){
        int len=0;
        if(x<0) putchar('-'),x=-x;
        do{ Ch[len++]=x%10+'0'; x/=10; }while(x);
        for(int i=len-1;~i;i--) putchar(Ch[i]); putchar(sp);
    }
} using namespace IO;

const int NN=250010;
int n,t,k,g,ans,m[NN];
int gcd(int a,int b){ return !b?a:gcd(b,a%b); }

bool check(int x){
    for(int i=n;i;i--){
        if(m[i]%x==0) return 0;
        if(m[i]<x) return 1;
    }
    return 1;
}

signed main(){
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    t=n=read(); k=read();
    for(int i=1;i<=k;i++) m[i]=read();
    ans=g=gcd(n,m[k]);
    for(int i=1;i<k;i++) m[i]=gcd(m[i],g);
    sort(m+1,m+k); n=unique(m+1,m+k)-m-1;
    for(int i=1;i*i<=g;i++) if(g%i==0){
        if(i<ans&&check(i)) ans=i;
        if(g/i<ans&&check(g/i)) ans=g/i;
    }
    write(t/ans,'\n');
    return 0;
}

T3 追逐

是原题。

树形DP,维护每个点走到子树叶子的最大值和从子树叶子走到这个点的最大值,合并即可。

\(code\):

T3
#include<bits/stdc++.h>
using namespace std;

namespace IO{
    typedef long long LL;
    int read(){
        int x=0,f=0; 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 f?-x:x;
    } char Ch[50];
    void write(LL x,char sp){
        int len=0;
        if(x<0) putchar('-'),x=-x;
        do{ Ch[len++]=x%10+'0'; x/=10; }while(x);
        for(int i=len-1;~i;i--) putchar(Ch[i]); putchar(sp);
    }
    void ckmax(LL& x,LL y){ x=x>y?x:y; }
} using namespace IO;

const int NN=100003;
int n,v;
LL ans,w[NN],deg[NN],up[NN][103],dn[NN][103];
vector<int>e[NN];
void add(int a,int b){
    e[a].push_back(b);
    e[b].push_back(a);
}

void dfs(int s,int f){
    for(int i=1;i<=v;i++)
        up[s][i]=deg[s],dn[s][i]=deg[s]-w[f];
    for(int t:e[s]) if(t!=f){
        dfs(t,s);
        for(int j=1;j<=v;j++) ckmax(ans,up[s][j]+dn[t][v-j]);
        for(int j=1;j<=v;j++){
            ckmax(up[s][j],up[t][j]);
            ckmax(dn[s][j],dn[t][j]);
            if(j){
                ckmax(up[s][j],up[t][j-1]+deg[s]-w[t]);
                ckmax(dn[s][j],dn[t][j-1]+deg[s]-w[f]);
            }
        }
    }
    reverse(e[s].begin(),e[s].end());
    for(int i=1;i<=v;i++)
        up[s][i]=deg[s],dn[s][i]=deg[s]-w[f];
    for(int t:e[s]) if(t!=f){
        for(int j=1;j<=v;j++) ckmax(ans,up[s][j]+dn[t][v-j]);
        for(int j=1;j<=v;j++){
            ckmax(up[s][j],up[t][j]);
            ckmax(dn[s][j],dn[t][j]);
            if(j){
                ckmax(up[s][j],up[t][j-1]+deg[s]-w[t]);
                ckmax(dn[s][j],dn[t][j-1]+deg[s]-w[f]);
            }
        }
    }
    ckmax(ans,max(up[s][v],dn[s][v]));
}

signed main(){
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    n=read(); v=read();
    for(int i=1;i<=n;i++) w[i]=read();
    for(int a,b,i=1;i<n;i++)
        a=read(),b=read(),add(a,b);
    for(int i=1;i<=n;i++)
        for(int t:e[i]) deg[i]+=w[t];
    dfs(1,0);
    write(ans,'\n');
    return 0;
}

T4 字符串

image

\(code:\)

T4
#include<bits/stdc++.h>
using namespace std;

namespace IO{
    int read(){
        int x=0,f=0; 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 f?-x:x;
    } char Ch[50];
    void write(int x,char sp){
        int len=0;
        if(x<0) putchar('-'),x=-x;
        do{ Ch[len++]=x%10+'0'; x/=10; }while(x);
        for(int i=len-1;~i;i--) putchar(Ch[i]); putchar(sp);
    }
    void ckmax(int& x,int y){ x=x>y?x:y; }
    void ckmin(int& x,int y){ x<y?x:y; }
} using namespace IO;

const int NN=500010;
int n,q,L,R;
char st[NN];

namespace Segment_Tree{
    #define ld rt<<1
    #define rd (rt<<1)|1
    struct node{
        int lx,rx,mx,sm;
        node(){ lx=rx=mx=sm=0; }
        node(int x){ lx=rx=mx=sm=x; }
        node operator+(const node& a)const{
            node res;
            res.lx=max(lx,sm+a.lx);
            res.rx=max(a.rx,rx+a.sm);
            res.mx=max(rx+a.lx,max(mx,a.mx));
            res.sm=sm+a.sm;
            return res;
        }
    }ans,s[NN<<2];
    void pushup(int rt){ s[rt]=s[ld]+s[rd]; }
    void build(int rt,int l,int r){
        if(l==r) return s[rt]=(st[l]=='C'?1:-1),void();
        int mid=l+r>>1;
        build(ld,l,mid); build(rd,mid+1,r);
        pushup(rt);
    }
    node query(int opl,int opr,int rt=1,int l=1,int r=n){
        if(l>=opl&&r<=opr) return s[rt];
        int mid=l+r>>1;
        if(opr<=mid) return query(opl,opr,ld,l,mid);
        if(opl>mid) return query(opl,opr,rd,mid+1,r);
        return query(opl,opr,ld,l,mid)+query(opl,opr,rd,mid+1,r);
    }
} using namespace Segment_Tree;

int calc(int l,int r){
    ans=query(l,r);
    return max(ans.mx,0)-ans.sm;
}

signed main(){
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    n=read(); scanf("%s",st+1);
    build(1,1,n); q=read();
    while(q--){ L=read(); R=read(); write(calc(L,R),'\n'); }
    return 0;
}
posted @ 2021-11-17 17:04  keen_z  阅读(33)  评论(0)    收藏  举报