zoukankan      html  css  js  c++  java
  • CF1083(div1)

    A. The Fair Nut and the Best Path

    题意:给定有点权,有边权的树,让你选择一条链(也可以是只有一个点),使得点权之和-边权最大。

    思路:裸的树形DP,我们用dp[i]表示i的子树里某个点到i这条链的最大值,然后用次大值更新答案即可。

    具体的,每个dp[i]初始化=a[i];  对于i连出去的边-> (i,j),用它来更新答案,max(ans,dp[i]+dp[j]-len[i,j]);然后用它更新dp[i],max(dp[i],dp[i]-len[i,j]);

    因为要的是最大值,肯定中途是大于等于0的,所以不会有中途油料耗尽的情况。
    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define ll long long
    using namespace std;
    const int maxn=1000010;
    int a[maxn],Laxt[maxn],Next[maxn],To[maxn],Len[maxn],cnt;
    ll dp[maxn],ans;
    void add(int u,int v,int c)
    {
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=c;
    }
    void dfs(int u,int f)
    {
        dp[u]=a[u]; if(a[u]>ans) ans=a[u];
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i]; if(v==f) continue;
            dfs(v,u);
            ans=max(ans,dp[u]+dp[v]-Len[i]);
            dp[u]=max(dp[u],dp[v]-Len[i]+a[u]);
        }
    }
    int main()
    {
        int N,u,v,c;
        scanf("%d",&N);
        rep(i,1,N) scanf("%d",&a[i]);
        rep(i,1,N-1){
            scanf("%d%d%d",&u,&v,&c);
            add(u,v,c); add(v,u,c);
        }
        dfs(1,0);
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    B:B. The Fair Nut and Strings

    题意:给定长度为N的由'a','b'组成的字符串S,T,满足S<=T,给出数字K,让你在[S,T]中找K个字符串,使得他们的value最大,value是指满足至少是K个字符串之一的前缀的字符串的个数。

    思路:把'a'看成0,'b'看成1,那么[S,T]之间的个数num=T-S+1;我们先使K=min(K,num)。

    题意转化一下:想象有深度为N的完全二叉树,左儿子是0,右儿子是1,分别把S和T划出来,由根到因子划成一条线,然后在这两条线之间找K条线,答案就是K条线路过的节点个数。显然第i层的贡献=min(K,2^i-边缘), 即除了最前面的线,和最后面的线,由上一层到下一层,节点数我们都可以*2;

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define ll long long
    using namespace std;
    const int maxn=500010;
    char a[maxn],b[maxn]; int N,K,x[maxn],y[maxn];
    bool check()
    {
        rep(i,1,N) x[i]=b[i]-a[i];
        for(int i=N;i>=1;i--){
            while(x[i]<0) x[i]+=2,x[i-1]-=1;
        }
        int tK=K;
        for(int i=N;i>=1;i--){
            if(!tK) break;
            y[i]=tK%2; tK/=2;
        }
        for(int i=1;i<=N;i++) {
            if(x[i]>y[i]) return true;
            if(x[i]<y[i]) return false;
        }
        return true;
    }
    void get()
    {
        K=1; for(int i=N;i>=1;i--){
            if(x[i]) K+=(1LL<<(N-i));
        }
    }
    int main()
    {
        int pos=0; ll ans=0; int tmp=1;
        scanf("%d%d",&N,&K);
        scanf("%s%s",a+1,b+1);
        if(!check()) get();
        rep(i,1,N){
             if(a[i]==b[i]) pos=i,ans++;
             else break;
        }
        rep(i,pos+1,N) {
            if(tmp<=K){
                tmp=tmp*2;
                if(a[i]=='b') tmp--;
                if(b[i]=='a') tmp--;
            }
            ans=ans+min(tmp,K);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    E. The Fair Nut and Rectangles

    (这个题太亏了,WA6,原因是没有用double!...不然这一次要上150分的....我的橙名啊

    题意:给出N个左下角是原点的矩形,每个矩形有自己的val,保证矩形之间没有包含关系,让你选择一些矩形,使得他们的面积并-val之和最大。

    思路:我们先给矩形排序,然后就是DP了,dp[i]=max(dp[j]+(y[i]-y[j])*x[i]-val[i]);

    明显的斜率优化,但是注意维护队首时要超过long long,注意使用double!

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define ll long long
    using namespace std;
    const int maxn=1000010;
    struct in{
        ll x,y,val;
        bool friend operator <(in w,in v){
            return w.x<v.x;
        }
    }s[maxn];
    ll ans,dp[maxn],head,top,q[maxn];
    ll DY(ll i)
    {
        return dp[i];
    }
    ll getans(ll i,ll j){
        return dp[j]+(s[i].y-s[j].y)*s[i].x-s[i].val;
    }
    int main()
    {
        int N; scanf("%d",&N);
        rep(i,1,N) scanf("%lld%lld%lld",&s[i].x,&s[i].y,&s[i].val);
        sort(s+1,s+N+1);
        for(ll i=N;i>=1;i--){
            while(head<top&&getans(i,q[head])<=getans(i,q[head+1])) head++;
            dp[i]=getans(i,q[head]); ans=max(ans,dp[i]);
            while(top>0&&1.0*(DY(i)-DY(q[top]))*(s[i].y-s[q[top-1]].y)>1.0*(DY(i)-DY(q[top-1]))*(s[i].y-s[q[top]].y)) top--;
            q[++top]=i;
        }
        printf("%lld
    ",max(ans,0LL));
        return 0;
    }
    View Code

    (过了AB,涨了75分...E要是过了的话...

    哭,菜死了

  • 相关阅读:
    遍历Map集合的方法
    简易循环手动增加表的数据
    初识Mysql,mysql的介绍和一些SQL语句
    SQL语句
    STS中applicationContext.xml配置文件
    STS中poem.xml配置文件
    MybatisMapper 动态映射(增删改查)
    MybatisMapper 映射框架(增删改查 原始模式)
    Spring 框架下 (增 删 改 )基本操作
    Spring 框架下 事务的配置(复杂)
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10101797.html
Copyright © 2011-2022 走看看