国庆节期间稍微做一下题......
题目链接:https://ac.nowcoder.com/acm/contest/1107#question
A.Easy h-index

#includeusing 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; }
B.Higher h-index
这道题居然是一道思维题,算了我半天方法不对还超时了。
其实我还没理解为啥要这样算,以下强行解释一波——
因为时间是有限的,所以通过花费时间获得的引用量是一定的,为了尽可能增大h,就要疯狂采取题中说的引用自己之前写的论文的方式,因此要让写出的论文数最多,每篇论文花1个小时就可以了。然后找规律,引用量最少的是a+0,最多的是a+n,间隔为1,所以答案是a+n/2。

#includeusing namespace std; int main() { int n,a; while(~scanf("%d%d",&n,&a)) { cout<<(n+a>>1)<<endl; } return 0; }
这道题还可以二分答案做,a+n/2只是一个结论好像。
K.2018
数学题,反正要算清楚就对了。

#includeusing 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; }
F.Sorting
cmp函数的写法,不能直接double c/a+b,然后比较,直接代式子。

#includeusing 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; }
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; }