• Codeforces Round #263 (Div. 1)-A,B,C


    A:

    这道题目还是非常easy的,做过非常多遍了。相似于分割木板的问题。

    把全部的数放在一个优先队列里,弹出两个最大的,然后合并,把结果放进去。依次进行。

    #include <iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    #include<vector>
    #include<algorithm>
    #include<string.h>
    #include<queue>
    using namespace std;
    #define LL __int64
    #define INF 1000000000
    LL a[330000];
    priority_queue<LL>que;
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            LL sum=0;
            while(!que.empty())que.pop();
            for(int i=1;i<=n;i++)
            {
                scanf("%I64d",&a[i]);
                sum+=a[i];
                que.push(a[i]);
            }
            LL ans=0;
            while(!que.empty())
            {
                LL x=que.top();
                que.pop();
                if(!que.empty())
                {
                    LL y=que.top();
                    que.pop();
                    ans+=x;
                    ans+=y;
                    que.push(x+y);
                }
                else
                {
                    ans+=x;
                    break;
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    B:树形DP

    dp[i][0]:以i节点为根的子树对上面的贡献为0时的情况数

    dp[i][1]:以i节点为根的子树对上面的贡献为1时的情况数

    假设i节点为0

    非常明显对于dp[i][1]:

    枚举哪颗子树对i贡献了1,假如a,b,c为i的子树,则

    dp[i][1]=dp[a][1]*dp[b][0]*dp[c][0]+dp[a][0]*dp[b][1]*dp[c][0]+dp[a][0]*dp[b][0]*dp[c][1];

    对于dp[i][0]:

    1,假设全部的子树都没有对i贡献

    dp[i][0]+=dp[a][0]*dp[b][0]*dp[c][0];

    2,存在一个子树对i贡献了1,可是i节点上方的边被切掉

    dp[i][0]+=dp[i][1];


    假设i节点为1

    dp[i][0]=dp[i][1]=dp[a][0]*dp[b][0]*dp[c][0];

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<set>
    #include<string>
    using namespace std;
    #define maxn 110000
    #define LL __int64
    #define mod 1000000007
    vector<int>old[maxn];
    vector<int>now[maxn];
    int vis[maxn];
    void change(int x)
    {
        int i;
        vis[x]=1;
        for(i=0; i<old[x].size(); i++)
        {
            if(vis[old[x][i]])continue;
            now[x].push_back(old[x][i]);
            change(old[x][i]);
        }
    }
    LL dp[maxn][2];
    int a[maxn];
    LL q_mod(LL a,LL b,LL n)
    {
        LL ret=1;
        LL tmp=a;
        while(b)
        {
            //基数存在
            if(b&0x1) ret=ret*tmp%n;
            tmp=tmp*tmp%n;
            b>>=1;
        }
        return ret;
    }
    LL dos(LL x,LL y,LL z)
    {
    
        x=x*z;
        x=x%mod;
        x=x*q_mod(y,mod-2,mod);
        x=x%mod;
        return x;
    }
    void dfs(int x)
    {
        int leap=0;
        LL sum=1;
        for(int i=0; i<now[x].size(); i++)
        {
            dfs(now[x][i]);
            leap=1;
            sum=sum*dp[now[x][i]][0];
            sum=sum%mod;
        }
        if(leap==0)
        {
            if(a[x]==0)
            {
                dp[x][0]=1;
                dp[x][1]=0;
            }
            else
            {
                dp[x][1]=1;
                dp[x][0]=1;
            }
             // cout<<x<<" "<<dp[x][1]<<" "<<dp[x][0]<<endl;
            return ;
        }
        if(a[x]==0)
        {
            dp[x][0]=sum;
            dp[x][1]=0;
            for(int i=0; i<now[x].size(); i++)
            {
                int y=now[x][i];
                dp[x][1]+=dos(sum,dp[y][0],dp[y][1]);
                dp[x][1]%=mod;
            }
            dp[x][0]+=dp[x][1];
            dp[x][0]%=mod;
        }
        else
        {
            dp[x][1]=sum;
            dp[x][0]=sum;
        }
       //  cout<<x<<" "<<dp[x][1]<<" "<<dp[x][0]<<endl;
    }
    int main()
    {
        int i,n,j;
        int aa,ab;
        while(~scanf("%d",&n))
        {
            memset(vis,0,sizeof(vis));
            for(i=0; i<=n; i++)
            {
                old[i].clear();
                now[i].clear();
            }
            for(i=1; i<n; i++)
            {
                scanf("%d",&aa);
                aa=aa+1;
                ab=i+1;
                //  cout<<" "<<aa<<" -" <<ab<<endl;
                old[aa].push_back(ab);
                old[ab].push_back(aa);
            }
            for(int i=1; i<=n; i++)scanf("%d",&a[i]);
            change(1);
            dfs(1);
            cout<<dp[1][1]<<endl;
        }
        return 0;
    }


    C:

    非常明显,假设翻转大于一半,相当于先旋转。然后翻转剩下的。

    那么我们最多会翻转2*n个数字。

    然后就暴力枚举当前的状态。

    然后用线段树储存每一个节点有多少长度,然后询问的时候区间求和。

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<set>
    #include<string>
    using namespace std;
    #define maxn 110000
    #define LL __int64
    #define mod 1000000007
    #define mem(a,b) (memset(a),b,sizeof(a))
    #define lmin 1
    #define rmax n
    #define lson l,(l+r)/2,rt<<1
    #define rson (l+r)/2+1,r,rt<<1|1
    #define root lmin,rmax,1
    #define now l,r,rt
    #define int_now int l,int r,int rt
    int have[maxn];
    int sum[maxn<<2];
    void creat(int_now)
    {
        if(l!=r)
        {
            creat(lson);
            creat(rson);
            sum[rt]=sum[rt<<1]+sum[rt<<1|1];
        }
        else
        {
            sum[rt]=1;
        }
    }
    void updata(int ll,int x,int_now)
    {
        if(ll>r||ll<l)return;
        if(ll==l&&l==r)
        {
            sum[rt]=x;
            return ;
        }
        updata(ll,x,lson);
        updata(ll,x,rson);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    int query(int ll,int rr,int_now)
    {
        if(ll>r||rr<l)return 0;
        if(ll<=l&&rr>=r)return sum[rt];
        return query(ll,rr,lson)+query(ll,rr,rson);
    }
    int leap,st,ed,n;
    void chu(int p)
    {
        if(leap==0)
        {
            st=st+p;
            ed=ed;
            for(int i=p; i>=1; i--)
            {
                have[st+i-1]=have[st+i-1]+have[st-i];
                updata(st+i-1,have[st+i-1],root);
            }
        }
        else
        {
            ed=ed-p;
            st=st;
            for(int i=p; i>=1; i--)
            {
                have[ed-i+1]=have[ed-i+1]+have[ed+i];
                updata(ed-i+1,have[ed-i+1],root);
            }
        }
    }
    int main()
    {
        int q;
        while(~scanf("%d%d",&n,&q))
        {
            creat(root);
            for(int i=1; i<=n; i++)have[i]=1;
            int len=n;
            leap=0;
            st=1;
            ed=n;
            int a,b,p,t;
            while(q--)
            {
                scanf("%d",&t);
                if(t==1)
                {
                    scanf("%d",&p);
                    len=ed-st+1;
                    int ban=len/2;
                    if(p<=ban)
                    {
                        chu(p);
                    }
                    else
                    {
                        len=ed-st+1;
                        p=len-p;
                        leap=leap^1;
                        chu(p);
                    }
                }
                else
                {
                    scanf("%d%d",&a,&b);
                    if(leap==0)
                    {
                        a=a+st;
                        b=b+st-1;
                    }
                    else
                    {
                        a=ed-a;
                        b=ed-b+1;
                        swap(a,b);
                    }
                    if(a>ed||b<st)
                    {
                        cout<<"0"<<endl;
                        continue;
                    }
                    if(b>ed)b=ed;
                    if(a<st)a=st;
                    cout<<query(a,b,root)<<endl;
                }
            }
        }
        return 0;
    }
    















  • 相关阅读:
    洛谷 P3392 涂国旗
    CODEVS 1066/洛谷 P1514引水入城
    POJ 1286 Necklace of Beads(项链的珠子)
    CODEVS 1138 聪明的质监员
    洛谷 P1241 括号序列
    C++之路进阶——codevs2313(星际竞速)
    C++之路进阶——codevs2366(朋友圈)
    c++之路进阶——hdu3507(Print Article)
    C++之路进阶——codevs2404(糖果)
    C++之路进阶——codevs4655(序列终结者)
  • 原文地址:https://www.cnblogs.com/llguanli/p/8477551.html
Copyright © 2020-2023  润新知