zoukankan      html  css  js  c++  java
  • 【学长出题】【比赛题解】17-09-29

    此次比赛由dalao学长@FallDream出题,欢迎查看他的blog!

    【T1】

    题意:

    样例:

    (1<=n<=100000, 1<=xi,yi<=10^9)

    题解:

    加一个骨牌,就相当于把最后的若干个骨牌删除,再算之前的答案。

    如果我们对任意的前i个骨牌算出答案,就可以简单地算出最终答案。

    就有了dp的想法,可以发现是比较简单的。

    f[i]=f[k]+(i-k),k是i推倒后最后一个没有被推倒的骨牌编号。

     1 #include<cstdio>
     2 #include<algorithm>
     3 typedef std::pair<int,int> P;
     4 P a[100001];
     5 int n,f[100001],Ans=100000;
     6 int main(){
     7     freopen("card.in","r",stdin);
     8     freopen("card.out","w",stdout);
     9     scanf("%d",&n);
    10     for(int i=1;i<=n;++i) scanf("%d%d",&a[i].first,&a[i].second);
    11     std::sort(a+1,a+n+1);
    12 //    for(int i=1;i<=n;++i) printf("%d %d
    ",a[i].first,a[i].second);
    13     for(int i=1;i<=n;++i){
    14         int R=std::lower_bound(a+1,a+n+1,P(a[i].first-a[i].second,0)) - a;
    15         f[i] = f[R-1] + i-R;
    16 //        printf("%d ",f[i]);
    17         if(Ans > f[i] + n-i) Ans = f[i] + n-i;
    18     }
    19     printf("%d",Ans);
    20     return 0;
    21 }

    【T2】

    题意:

    样例:

    题解:

    易证,一个数组的海棠度,一定有(j=i+1)。

    那么,如果记(dif_{i}=left|a_{i+1}-a_{i} ight|left(1leqslant i<n ight)),就能把题目转化成求某个区间中所有子串的最大值之和。

    考虑枚举最大值的位置,计算能使它成为最大值的区间个数。

    我们需要求出某个数往左第一个大于它的数的位置,往右第一个不小于它的数的位置。

    而这是能够使用单调栈维护的。

    统计答案时用乘法原理,注意开ll。

     1 #include<cstdio>
     2 const int INF=2147483647;
     3 int n,q,a[100001],left[100001],right[100001],l,r;
     4 int stk[100001],top=0;
     5 inline int Abs(int e){return e>0?e:-e;}
     6 inline int Min(int p,int q){return p<q?p:q;}
     7 inline int Max(int p,int q){return p>q?p:q;}
     8 int main(){
     9     freopen("array.in","r",stdin);
    10     freopen("array.out","w",stdout);
    11     scanf("%d%d",&n,&q);
    12     for(int i=1;i<=n;++i) scanf("%d",a+i);
    13     for(int i=1;i<n;++i) a[i]=Abs(a[i+1]-a[i]);
    14     n--;
    15     a[0]=a[n+1]=INF;
    16     top=0; stk[++top]=0;
    17     for(int i=1;i<=n;++i){
    18         while(top&&a[stk[top]]<=a[i]) --top;
    19         left[i]=stk[top]+1;
    20         stk[++top]=i;
    21     }
    22     top=0; stk[++top]=n+1;
    23     for(int i=n;i>=1;--i){
    24         while(top&&a[stk[top]]<a[i]) --top;
    25         right[i]=stk[top]-1;
    26         stk[++top]=i;
    27     }
    28 //    for(int i=1;i<=n;++i) printf("%d ",a[i]); puts("");
    29 //    for(int i=1;i<=n;++i) printf("%d ",left[i]); puts("");
    30 //    for(int i=1;i<=n;++i) printf("%d ",right[i]); puts("");
    31     while(q--){
    32         long long sum=0;
    33         int ll,rr;
    34         scanf("%d%d",&l,&r);
    35         for(int i=l;i<r;++i){
    36             ll=Max(l,left[i]);
    37             rr=Min(r-1,right[i]);
    38             sum+=1ll*a[i]*(i-ll+1)*(rr-i+1);
    39         }
    40         printf("%lld
    ",sum);
    41     }
    42     return 0;
    43 }

    【T3】

    题意:

    样例:

    题解:

    考虑把所有怪物分成两类,(a_{i}<b_{i})的和(a_{i}geqslant b_{i})的。

    那么,我们先打①类怪物,一定没毛病……

    把①类怪物按照(a_{i})从小到大排序,一个个尝试能否打败。

    对于②类怪物我们反过来考虑,先计算出打完所有怪物后的生命值({h}'),然后将②类怪物的(a_{i})与(b_{i})交换,相同处理。

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstdio>
     4 #define pa pair<int,int>
     5 #define MN 200000
     6 using namespace std;
     7 inline int read()
     8 {
     9     int x=0;char ch=getchar();
    10     while(ch<'0'||ch>'9')ch=getchar();
    11     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    12     return x;
    13 }
    14 int n,top1=0,top2=0,a[MN+5],b[MN+5],rk1[MN+5],rk2[MN+5],id1[MN+5],id2[MN+5];long long m,M;
    15 pa q1[MN+5],q2[MN+5];
    16 bool cmp1(int x,int y){return q1[x]<q1[y];}
    17 bool cmp2(int x,int y){return q2[x]<q2[y];}
    18 int main()
    19 {
    20     freopen("atm.in","r",stdin);
    21     freopen("atm.out","w",stdout);
    22     n=read();M=m=read();
    23     for(int i=1;i<=n;++i)
    24     {
    25         int x=read(),y=read();M+=y-x;
    26         if(x<=y) q1[++top1]=make_pair(x,y),id1[top1]=i;
    27         else q2[++top2]=make_pair(y,x),id2[top2]=i;
    28         rk1[i]=rk2[i]=i;
    29     }
    30     if(M<0) return 0*puts("-1");
    31     sort(rk1+1,rk1+top1+1,cmp1);sort(rk2+1,rk2+top2+1,cmp2);
    32     for(int i=1;i<=top1;++i)
    33     {
    34         int x=rk1[i];
    35         if((m-=q1[x].first)<=0) return 0*puts("-1");
    36         m+=q1[x].second;
    37     }
    38     for(int i=1;i<=top2;++i)
    39     {
    40         int x=rk2[i];
    41         if((M-=q2[x].first)<=0) return 0*puts("-1");
    42         M+=q2[x].second;
    43     }
    44     for(int i=1;i<=top1;++i) printf("%d ",id1[rk1[i]]);
    45     for(int i=top2;i;--i) printf("%d ",id2[rk2[i]]);
    46     return 0;
    47 }
  • 相关阅读:
    CAS配置记录
    线程同步机制
    线程
    异常
    List集合
    数据结构
    泛型+通配符高级使用--受限泛型
    Collection集合+迭代器+foreach循环
    easyui获取日期datebox中的值
    EL表达式与三目运算符
  • 原文地址:https://www.cnblogs.com/PinkRabbit/p/7612223.html
Copyright © 2011-2022 走看看