2019牛客国庆集训派对day2

国庆节期间稍微做一下题......

题目链接:https://ac.nowcoder.com/acm/contest/1107#question

A.Easy h-index

#include
using namespace std;
const int maxn=2e5+20;
typedef long long ll;
ll s[maxn];

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<=n;i++)
        {
            int x;
            cin>>x;
            if(i==0) s[i]=(ll)x;
            else s[i]=s[i-1]+(ll)x; //记录前0-i个引用的文章总数
        }
        int ans=0;
        for(int i=n;i>=1;i--) //也可以从小到大遍历,这样就不用break
        {
            if(s[n]-s[i-1]>=i)
            {
                ans=i;
                break;
            }         
        }
        cout<endl;
    }
    return 0;
}
View Code

B.Higher h-index

这道题居然是一道思维题,算了我半天方法不对还超时了。

其实我还没理解为啥要这样算,以下强行解释一波——

因为时间是有限的,所以通过花费时间获得的引用量是一定的,为了尽可能增大h,就要疯狂采取题中说的引用自己之前写的论文的方式,因此要让写出的论文数最多,每篇论文花1个小时就可以了。然后找规律,引用量最少的是a+0,最多的是a+n,间隔为1,所以答案是a+n/2。

#include
using namespace std;

int main()
{
    int n,a;
    while(~scanf("%d%d",&n,&a))
    {
        cout<<(n+a>>1)<<endl;
    }
    return 0;
}
View Code

这道题还可以二分答案做,a+n/2只是一个结论好像。

K.2018

数学题,反正要算清楚就对了。

#include
using namespace std;
typedef long long ll;

int main()
{
    int a,b,c,d;
    while(~scanf("%d%d%d%d",&a,&b,&c,&d))
    {
        ll ans;
        int e1,e2,o1,o2,x1,x2,y1,y2;
        e1=b/2-(a-1)/2;  
        e2=d/2-(c-1)/2;  //偶数个数
        x1=(b/1009-(a-1)/1009);
        x2=(b/2018-(a-1)/2018);  //2018的倍数
        x1-=x2;  //1009的奇数倍
        y1=(d/1009-(c-1)/1009);
        y2=(d/2018-(c-1)/2018);
        y1-=y2;
        ans=(ll)y2*(b-a+1)+(ll)x2*(d-c+1)+(ll)e1*y1+(ll)e2*x1;
        ans-=(ll)x2*y2+(ll)x2*y1+(ll)x1*y2; //减去重复项
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 F.Sorting

cmp函数的写法,不能直接double c/a+b,然后比较,直接代式子。

#include
using namespace std;
typedef unsigned long long ull;
struct node
{
    ull a,b,c;
    int id;
}n[1005];
bool cmp(node x,node y)
{
    if((x.a+x.b)*y.c==(y.a+y.b)*x.c) return x.id<y.id;
    return (y.a+y.b)*x.c>(x.a+x.b)*y.c;   //这样比较也可以
}
int main()
{
    int t;
    while(~scanf("%d",&t))
    {
        for(int i=0;i)
        {
            cin>>n[i].a>>n[i].b>>n[i].c;
            n[i].id=i+1;
        }
        sort(n,n+t,cmp);
        for(int i=0;i)
            cout<' ';
        printf("\n");
    }
    return 0;
}
View Code

 C.Just h-index

可持续化线段树,大约学了一下。

维护的是1-maxn的引用区间内论文个数(这个没想到),分别建T[0],T[1],,,,,T[n]树,然后看T[l-1]到T[r]各结点的个数变化,二分答案0-maxn查询。

#include
#include
#include
using namespace std;

const int maxn=1e5+7;
int T[maxn],L[maxn*20],R[maxn*20],sum[maxn*20]; //注意大小4+16约为20
int tot; //结点总数,全局变量

void build(int &rt,int l,int r)
{
    rt=++tot;
    sum[rt]=0;
    if(l==r)
        return;
    int m=(l+r)>>1;//¿É²»¼ÓÀ¨ºÅ
    build(L[rt],l,m);
    build(R[rt],m+1,r);
}
int query(int s,int e,int l,int r,int x)
{
    if(l==r) return sum[e]-sum[s];  //末态-始态
    int m=(l+r)>>1;
    if(x<=m) return sum[R[e]]-sum[R[s]]+query(L[s],L[e],l,m,x);
    else return query(R[s],R[e],m+1,r,x);
}
void update(int &rt,int l,int r,int pre,int x)
{
    rt=++tot;
    L[rt]=L[pre]; //该节点的原左结点
    R[rt]=R[pre];
    sum[rt]=sum[pre]+1;
    if(l==r)
        return;
    int m=(l+r)>>1;
    if(x<=m) update(L[rt],l,m,L[pre],x);
    else update(R[rt],m+1,r,R[pre],x);
}
int main()
{
    int n,q;
    while(~scanf("%d%d",&n,&q))
    {
        tot=0;
        build(T[0],1,maxn);  //建T[0]空树
        for(int i=1;i<=n;i++)
        {
            int a;
            scanf("%d",&a);
            update(T[i],1,maxn,T[i-1],a);
        }
        for(int i=1;i<=q;i++)
        {
            int ql,qr;
            scanf("%d%d",&ql,&qr);
            int l=0,r=maxn,ans=0;  //答案可能为0
            while(l<=r)
            {
                int mid=l+r>>1;
                int h=query(T[ql-1],T[qr],1,maxn,mid); //二分答案查询
                if(h>=mid)
                {
                    ans=mid;
                    l=mid+1;
                }
                else r=mid-1;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
View Code

 

你可能感兴趣的:(2019牛客国庆集训派对day2)