zoukankan      html  css  js  c++  java
  • CF 1041 1042整理

    终于回来整理了,这两场比赛我也是醉了,第一场-1分,第二场被skip,还是太菜啊qaq

    CF1041

    T1T2过水忽略直接看后面

    T3大意:给你一个长度为n的序列a1,a2,a3···an,你需要把这些数分成若干组,使得每组数任意两数之差严格大于d,并且满足组数尽可能少。

    sol:有理有据的贪心。开一个小根堆,存入每一组的最大的数,当有一个新的数字时,判断它是否大于堆顶的元素+d,若满足就把当前元素归入哪一组并更新小根堆,否则新开一个编号,压入堆中。

    #include <queue>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=200005;
    struct data{int p,q;}a[N];
    inline bool cmp(data a,data b){return a.p<b.p;}
    struct node{int num,id;};
    priority_queue<node>q;
    inline bool operator<(const node &p,const node &q){return p.num>q.num;}
    int n,m,d,re=0,b[N];
    int main()
    {
        int i; scanf("%d%d%d",&n,&m,&d); for(i=1;i<=n;i++)scanf("%d",&a[i].p),a[i].q=i;
        sort(a+1,a+n+1,cmp); re=1; q.push((node){a[1].p,1}); b[a[1].q]=1;
        for(i=2;i<=n;i++)
        {
            node tmp=q.top();
            if(tmp.num+d<a[i].p)
            {
                q.pop(); q.push((node){a[i].p,tmp.id}); b[a[i].q]=tmp.id;
            }
            else
            {
                re++; q.push((node){a[i].p,re}); b[a[i].q]=re;
            }
        }printf("%d
    ",re); for(i=1;i<n;i++)printf("%d ",b[i]); printf("%d",b[n]);
    }
    View Code

    T4大意:你当前高度为h,你每往前飞一个单位就会下降一个单位(不能贴地飞行),给出n段气流,在气流中你不会下降,求你可以飞的最远距离(不限制起点)ps:气流从左到右有序给出。

    sol:先对1~n段气流做一个前缀和,记录1~i段会下降的距离和会向前滑行的距离,易知起点一定是某段气流的左端点(不然开始就白白下降),所以枚举左端点,二分右端点最远可能的位置,得到答案。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=200005;
    #define int long long
    int n,h,ans=0,s[N],su[N];
    struct node{int x,y;}a[N];
    inline bool jud(int S,int T)
    {
      if(s[T]-s[S]<h)return true; else return false;
    }
    signed main()
    {
      int i,l,r,mid,tmp; scanf("%lld%lld",&n,&h);    for(i=1;i<=n;i++)scanf("%lld%lld",&a[i].x,&a[i].y),ans=max(ans,a[i].y-a[i].x+h);
      for(i=2;i<=n;i++)s[i]=s[i-1]+a[i].x-a[i-1].y; for(i=1;i<=n;i++)su[i]=su[i-1]+a[i].y-a[i].x;
      for(i=1;i<=n;i++)
      {
        l=i,r=n,mid,tmp;
        while(l<=r)
        {
          mid=(l+r)/2; if(jud(i,mid))l=mid+1,tmp=mid;else r=mid-1;
        }ans=max(ans,su[tmp]-su[i-1]+h);
      }printf("%lld
    ",ans);
    }
    View Code

     T5大意:有一棵树,现在给你每条树边被去掉时,形成的两个联通块中点的最大的编号分别是多少,问满足条件的树存不存在,若存在请构造出这棵树

    sol:每条边一定有一端的最大值为n,所以我们就围着n建菊花图就好了,左右两端最大值相同的边就串成一条链接在n上

    #include <cstdio>
    #include <vector>
    #include <cstring>
    using namespace std;
    const int N=1005;
    int n,in1[N],a[N],b[N],n1=0,n2=0;
    bool G[N][N];
    vector<int>V[N];
    int main()
    {
        int i,j,x,y,bo=0; scanf("%d",&n); memset(in1,0,sizeof in1);
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y); if(y!=n)return 0*printf("NO
    "); in1[x]++;
        }
        for(i=1;i<n;i++)if(!in1[i])a[++n1]=i;else b[++n2]=i;
        for(i=1,j=1;i<=n2;i++)
        {
            if(in1[b[i]]>1)
            {
                in1[b[i]]--;
                while(in1[b[i]]>0&&j<=n1)
                {
                    if(b[i]<a[j]){bo=1;break;}
                    V[b[i]].push_back(a[j]); in1[b[i]]--; j++;
                }if(bo)break;
            }else G[b[i]][n]=1;
        }
        if(!bo)
        {
            for(i=1;i<n;i++)
            {
                if(V[i].size())
                {
                    for(j=0;j<V[i].size()-1;j++)
                    {
                        G[V[i][j]][V[i][j+1]]=1;
                    }G[i][V[i][0]]=1; G[V[i][V[i].size()-1]][n]=1;
                }
            }printf("YES
    ");
            for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(G[i][j])printf("%d %d
    ",i,j);
        }else return 0*printf("NO
    ");
    }
    View Code

    CF1042

    T3大意:给出一个长度为n的序列,每次可以合并两个数ax,ay(ax会消失,ay变成ax*ay),你还有一个机会可以删除一个数,使得最后得到的数最大

    sol:大力高精 想都别想 于是乎发现:如果负数有奇数个,那么要删除绝对值最小的那个,如果有0的话,先把0合成一个,以上两样如都有,则合在一起去掉反之则去掉存在的那个,(与此同时要注意,如果只剩一个数,是万万不能删掉的,不要问为什么,全删了答案是什么qaq)

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=200005;
    int n,m,a[N],cnt=0,v[N];
    int main()
    {
        int i,j,po=0,bo=0; scanf("%d",&n); m=n; for(i=1;i<=n;i++)scanf("%d",&a[i]); if(n==1)return 0;
        for(i=1;i<=n;i++)
        {
            if(a[i]<0) {bo++; if(!po)po=i; else if(a[po]<a[i])po=i;}
            else if(a[i]==0)v[++cnt]=i;
        }i=1;
        while(i<cnt)
        {
            printf("1 %d %d
    ",v[i],v[i+1]); i++; m--; if(m==1) return 0;
        }
        if(bo&1)
        {
            if(cnt)
            {
                printf("1 %d %d
    ",min(po,v[cnt]),max(po,v[cnt])); m--; if(m!=1)printf("2 %d
    ",max(po,v[cnt])); else return 0;
            }
            else
            {
                printf("2 %d
    ",po);
            }j=0;
            for(i=1;i<=n&&j<=n;)
            {
                while((a[i]==0||i==po)&&i<=n)i++; j=i+1; while((a[j]==0||j==po)&&j<=n)j++; if(j>n)return 0;
                printf("1 %d %d
    ",i,j); i=j; j=i+1; m--; if(m==1)return 0;
            }
        }
        else
        {
            po=0;
            if(cnt)
            {
                printf("2 %d
    ",v[cnt]);
            }j=0;
            for(i=1;i<=n&&j<=n;)
            {
                while((a[i]==0||i==po)&&i<=n)i++; j=i+1; while((a[j]==0||j==po)&&j<=n)j++; if(j>n)return 0;
                printf("1 %d %d
    ",i,j); i=j; j=i+1; m--; if(m==1)return 0;
            }
        }
    }
    View Code

    T4大意:给出一个长度为n的序列和一个数d,找出所有连续的子串使得其和小于d,求子串个数

    sol:树状数组加二分,先计算前缀和,离散一下,从1~n枚举每个前缀和,统计比s[i]-d大的个数,最后算一下有几个前缀和小于d,加入答案就完了,似乎比T3要水

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define int long long
    const int N=200005;
    int n,m,t,tot=0,s[N],tr[N],pre[N];
    struct node{int w,id,nid;}a[N];
    inline bool cmp(node a,node b){return a.w<b.w;}
    inline bool cmp1(node a,node b){return a.id<b.id;}
    #define lowbit(x) ((x)&(-x))
    inline void ins(int x){while(x>0){tr[x]++;x-=lowbit(x);}}
    inline int que(int x){int re=0;while(x<=tot){re+=tr[x];x+=lowbit(x);}return re;}
    inline int ask(int v)
    {
        int l=1,r=tot+1,mid,tmp=tot+1;
        while(l<=r)
        {
            mid=(l+r)>>1;if(pre[mid]>=v)r=mid-1,tmp=mid;else l=mid+1;
        }if(pre[tmp]==v)return tmp+1;else return tmp; 
    }
    signed main()
    {
        int i,x,ans=0,po; scanf("%lld%lld",&n,&t);
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&x); s[i]=s[i-1]+x; a[i].w=s[i]; a[i].id=i;
        }sort(a+1,a+n+1,cmp); tot=1; pre[1]=a[1].w; a[1].nid=1;
        for(i=2;i<=n;i++)
        {
            if(a[i].w!=a[i-1].w){tot++;pre[tot]=a[i].w;} a[i].nid=tot;
        }sort(a+1,a+n+1,cmp1);
        for(i=1;i<=n;i++)
        {
            po=ask(pre[a[i].nid]-t); ans+=que(po); ins(a[i].nid);
        }
        for(i=1;i<=n;i++)if(s[i]<t)ans++; printf("%lld
    ",ans);
    }
    View Code
  • 相关阅读:
    static作用(修饰函数、局部变量、全局变量)(转)
    地弹
    开漏(open drain)和开集(open colletor)
    过冲、振铃,非单调性
    串扰(crosstalk)
    数字通信基本概念
    电源和地
    分布式系统与集总系统
    传输线及其特性阻抗
    MSP430G2553 Launchpad 硬件I2C驱动
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/9691043.html
Copyright © 2011-2022 走看看