zoukankan      html  css  js  c++  java
  • CF595 Div31249A,1249B1,1249B2,1249C1,1249C2,1249D1,1249D2,1249E,1249F)题解

    A:水题,先排序,有相连的输出2,否则输出1.

    #include<bits/stdc++.h>
    using namespace std;
    #define pii pair<int,int>
    #define mkp make_pair
    #define pb push_back
    #define fi first
    #define se second
    typedef long long ll;
    const int INF=0x3f3f3f3f;
    int q,n;
    const int maxn=110;
    int a[maxn];
     
     
    int main()
    {
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;++i) scanf("%d",a+i);
            sort(a+1,a+1+n);
            int cnt=1;
            for(int i=2;i<=n;++i)
            {
                if(a[i]-a[i-1]==1) {cnt=2;break;}
            }
            printf("%d
    ",cnt);
        }
        
        return 0;
    }
    View Code

    B1和B2: 水题:同一个循环里面的步数一样,O(N)跑一遍即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define pii pair<int,int>
    #define mkp make_pair
    #define pb push_back
    #define fi first
    #define se second
    typedef long long ll;
    const int INF=0x3f3f3f3f;
    int q,n;
    const int maxn=2e5+10;
    int p[maxn],cnt[maxn],vis[maxn];
     
     
    int main()
    {
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;++i) scanf("%d",p+i),cnt[i]=vis[i]=0;
            for(int i=1;i<=n;++i)
            {
                if(vis[i]) continue;
                int ans=1,num=p[i];vis[i]=i;
                while(num!=i)
                {
                    num=p[num];
                    vis[num]=i;
                    ans++;
                }
                cnt[i]=ans;
            }
            for(int i=1;i<=n;++i) 
                printf("%d%c",cnt[vis[i]],i==n?'
    ':' ');
        }
        
        return 0;
    }
    View Code

    C1和C2: 水题:很显然>=n的最大的只要把n里面所有的3的幂去除,然后把剩下未选中的挑一个最小的且比去除之后的n大的加入答案就行。注意到样例里面给的最大的那个是3^38.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll a[40];
    void prework()
    {
        a[0]=1;
        for(int i=1;i<=39;++i) a[i]=a[i-1]*3;
    }
     
    int q;
    ll n,cn;
     
    int main()
    {
        prework();
        scanf("%d",&q);
        while(q--)
        {
            scanf("%lld",&n);
            ll ans=0; cn=n;
            int flag=-1,tmp=-1,tt=0;
            for(int i=38;i>=0;--i) 
            {
                if(n==a[i]){ans=a[i];tt=1;break;}
                if(a[i]<n){tmp=i+1;break;}    
            }
            if(tt){printf("%lld
    ",ans);continue;}
            
            for(int i=tmp-1;i>=0;--i)
            {
                if(n==a[i]){ans+=a[i];tt=1;break;}
                if(n>a[i]) {n-=a[i];ans+=a[i];}
                else flag=i; 
            }
            if(tt){printf("%lld
    ",ans);continue;}
            
            if(flag!=-1)
            {
                for(int i=0;i<flag;++i) ans-=a[i];
                ans+=a[flag];
            }
            else ans=a[tmp];
        
            printf("%lld
    ",ans);
        }
        
        return 0;    
    } 
    View Code

    D1和D2:

    D1可以暴力:set维护答案。

    #include<bits/stdc++.h>
    using namespace std;
    #define pii pair<int,int>
    #define mkp make_pair
    #define pb push_back
    #define fi first
    #define se second
    typedef long long ll;
    const int INF=0x3f3f3f3f;
     
    const int maxn=210;
    int k,n,cnt[maxn],vis[maxn];
    struct Node{
        int l,r,id;
    }p[maxn];
    bool cmp(Node &a,Node &b){return a.r<b.r;}
    vector<Node> v[maxn];
    set<int> st;
     
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;++i)
        { 
            scanf("%d%d",&p[i].l,&p[i].r);p[i].id=i;
            for(int j=p[i].l;j<=p[i].r;++j)
                v[j].push_back(Node{p[i].l,p[i].r,i}),cnt[j]++;
        } 
        //for(int i=1;i<=200;++i) cout<<cnt[i]<<endl;
        for(int i=1;i<=200;++i) 
            sort(v[i].begin(),v[i].end(),cmp);
        for(int i=1;i<=200;++i)
        {
            if(cnt[i]>k) 
            {
                int nn=cnt[i]-k;
                for(int j=v[i].size()-1;j>=0&&nn;--j)
                { 
                    if(vis[v[i][j].id]) continue;
                    st.insert(v[i][j].id),nn--; 
                    vis[v[i][j].id]=1;
                    for(int k=v[i][j].l;k<=v[i][j].r;++k)
                        cnt[k]--; 
                } 
            }
        }
        int len=st.size();
        printf("%d
    ",len);
        set<int>::iterator it;
        for(it=st.begin();it!=st.end();++it)
            printf("%d ",(*it));
        puts("");
        
            
        return 0;
    }
    View Code

    D2用线段树。按照 r 从小到大排序。然后从i 1-n枚举,如果区间最大值<k,则加入该线段,否则该线段必须去掉,加入答案集合里面即可。

    最后依次输出答案;

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    int res[maxn],ans,s[maxn],add[maxn],x,cnt,k,n,Max;
    struct Node{
        int l,r,id;
        bool operator<(const Node&p)const{
            return r^p.r?r<p.r:l<p.l;
        }
    }a[maxn];
    void pushdown(int l,int r,int rt)
    {
        int mid=l+r>>1;
        add[rt<<1]+=add[rt],add[rt<<1|1]+=add[rt];
        s[rt<<1]+=add[rt],s[rt<<1|1]+=add[rt];
        add[rt]=0;
    }
    void update(int l,int r,int rt,int u,int v)
    {
        if(l>v||r<u) return;
        if(l>=u&&r<=v)
        {
            s[rt]+=x,add[rt]+=x;
            return;
        }
        if(add[rt]) pushdown(l,r,rt);
        int mid=l+r>>1;
        update(l,mid,rt<<1,u,v);
        update(mid+1,r,rt<<1|1,u,v);
        s[rt]=max(s[rt<<1],s[rt<<1|1]);
    }
    void query(int l,int r,int rt,int u,int v)
    { 
        if(l>v||r<u) return;
        if(l>=u&&r<=v)
        { 
            ans=max(ans,s[rt]);
            return;
        }
        if(add[rt]) pushdown(l,r,rt);
        int mid=l+r>>1;
        query(l,mid,rt<<1,u,v);query(mid+1,r,rt<<1|1,u,v);
        s[rt]=max(s[rt<<1],s[rt<<1|1]);
    }
    int main()
    {  
        scanf("%d%d",&n,&k);
        Max=cnt=0;
        for(int i=1;i<=n;++i) 
        {
            scanf("%d%d",&a[i].l,&a[i].r);a[i].id=i; 
            Max=max(Max,a[i].r);    
        }
        
        sort(a+1,a+1+n);x=1;
        for(int i=1;i<=n;++i)
        {
            int u=a[i].l,v=a[i].r; ans=0;
            query(1,Max,1,u,v); 
            if(ans<k) update(1,Max,1,u,v);
            else res[++cnt]=a[i].id;
        }
        printf("%d
    ",cnt);
        sort(res+1,res+1+cnt);
        for(int i=1;i<=cnt;++i) 
            printf("%d%c",res[i],i==cnt?'
    ':' ');
        return 0;
    }
    View Code

    E:水题:DP即可。设f[i][0],f[i][1]表示选择楼梯和电梯的状态,直接按照题意模拟就行。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e6+10;
    int a[N],b[N],f[N][2],n,c;
    int main()
    {  
        scanf("%d%d",&n,&c);--n;
        for(int i=1;i<=n;++i) scanf("%d",a+i);
        for(int i=1;i<=n;++i) scanf("%d",b+i);
        f[0][1]=1e9;
        for(int i=1;i<=n;++i) f[i][0]=min(f[i-1][0],f[i-1][1])+a[i],f[i][1]=min(f[i-1][0]+c,f[i-1][1])+b[i];
        printf("0 ");for(int i=1;i<=n;++i) printf("%d ",min(f[i][0],f[i][1])); puts("");
        return 0;
    }
    View Code

    F题:暴力贪心。n<=200直接暴力找从深度为n开始距离k以内的点集和。

    贪心的取比较大的值即可。
    将所有点按照深度从大到小排序,如果当前点点权a[i]大于0,则将距离为k以内的所有点减a[i]
    代表取了当前点,为答案贡献a[i]
    如果下面又扫到大于零的点权,说明那个点比这个大,于是取那个

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10; 
    int n,k,a[maxn],t,nw,u,v,d[maxn],ans;
    vector<int> g[maxn];
    struct Edge{
        int v,nxt;
    } edge[maxn<<1];
    int head[maxn],tot;
    void AddEdge(int u,int v)
    {
        edge[tot].v=v;edge[tot].nxt=head[u];head[u]=tot++;
        edge[tot].v=u;edge[tot].nxt=head[v];head[v]=tot++;
    }
    void dfs(int x,int fa)
    {
        g[d[x]=d[fa]+1].push_back(x);
        for(int i=head[x],j;~i;i=edge[i].nxt)
            if((j=edge[i].v)!=fa) dfs(j,x);
    }
    void dfs2(int x,int fa,int dep)
    {
        a[x]-=nw;
        if(dep==k) return;
        for(int i=head[x],j;~i;i=edge[i].nxt)
            if((j=edge[i].v)!=fa) dfs2(j,x,dep+1);
    }
    int main()
    {  
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;++i) scanf("%d",a+i),head[i]=-1;
        for(int i=1;i<n;++i) scanf("%d%d",&u,&v),AddEdge(u,v);
        dfs(1,0);
        for(int i=n;i;--i)
            for(int j=0,sz=g[i].size(),x;j<sz;++j)
                if((x=a[g[i][j]])>0) nw=x,ans+=x,dfs2(g[i][j],0,0);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    STL源码剖析之_allocate函数
    PAT 1018. Public Bike Management
    PAT 1016. Phone Bills
    PAT 1012. The Best Rank
    PAT 1014. Waiting in Line
    PAT 1026. Table Tennis
    PAT 1017. Queueing at Bank
    STL源码剖析之list的sort函数实现
    吃到鸡蛋好吃,看看是哪只母鸡下的蛋:好用的Sqlite3
    cJSON
  • 原文地址:https://www.cnblogs.com/csushl/p/11729886.html
Copyright © 2011-2022 走看看