2018 湘潭邀请赛 题解 A C F G K .其它题解,后续添加
A 题
没啥好讲的,签到题 从后面往前面数,大于个数的时候直接输出就行了。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const long long mod=1e9+7;
const int maxn=2e5+25;
const int INF=0x7fffffff;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
int main() {
int n,a[maxn];
long long sum=0;
while(scanf("%d",&n)!=EOF) {
sum=0;
for(int i=0; i<=n; i++) {
scanf("%d",&a[i]);
}
for(int i=n; i>=0; i--) {
sum+=a[i];
if(sum>=i) {
printf("%d\n",i);
break;
}
}
}
return 0;
}
C题
题目的意思就是找一个区间比 一个数大的数的个数要不小于这个数。求这个数最大是多少。
这一题就是一个区域树(大佬们告诉我也叫主席树,然而我这个菜鸡不知道啥是主席树),一般线段树维护的是一个值。这题每个节点维护的是一个数组,这个题没有修改只有查询。
1. 每次查询在包含这个区间就二分查找大于这个数的个数,
2. 如果 不包含返回零。
3. 如果有一部分在这个区间就继续往下找,然后返回两个儿子的个数和。
复杂度是(nlogn+m log^3 n);
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const long long mod=1e9+7;
const int maxn=1e7+25;
const int INF=0x7fffffff;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const int sz=(1<<18)-1;
int n,m;
int a[maxn];
vector<int> dat[sz];
void init(int k,int l,int r) {
dat[k].clear();
if(r-l==1)dat[k].push_back(a[l]);
else {
int lch=k*2+1,rch=k*2+2,md=(l+r)/2;
init(lch,l,md);
init(rch,md,r);
dat[k].resize(r-l);
merge(dat[lch].begin(),dat[lch].end(),dat[rch].begin(),dat[rch].end(),dat[k].begin());
}
}
int query(int i,int j,int x,int k,int l,int r) {
if(j<=l||r<=i)return 0;
else if(i<=l&&r<=j) {
return dat[k].end()-lower_bound(dat[k].begin(),dat[k].end(),x);
} else {
int lch=2*k+1,rch=2*k+2,md=(l+r)/2;
return query(i,j,x,lch,l,md)+query(i,j,x,rch,md,r);
}
}
int main() {
while(~scanf("%d%d",&n,&m)) {
for(int i=0; i<n; i++) {
scanf("%d", &a[i]);
}
init(0,0,n);
int l,r,R,L,x;
for(int i=0; i<m; i++) {
scanf("%d%d",&l,&r);
l--;
L=1;
R=n;
while(R-L>1) {
x=(R+L)/2;
int c=query(l,r,x,0,0,n);
if(c>=x)L=x;
else R=x;
}
printf("%d\n",L);
}
}
return 0;
}
F题
一个sort 就过了没啥难的,就是注意值爆了double 要用long double。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const long long mod=1e9+7;
const int maxn=1e3+25;
const int INF=0x7fffffff;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
struct two {
long double val;
int id;
} k[maxn];
bool cmp(two & a,two &b) {
if(a.val==b.val)return a.id<b.id;
return a.val<b.val;
}
int main() {
int n;
long long a,b,c,d;
while(~scanf("%lld",&n)) {
for(int i=0; i<n; i++) {
scanf("%lld%lld%lld",&a,&b,&c);
long double t=0;
t=a*1.0;
t+=b*1.0;
t=t/(t+c*1.0);
k[i].id=i;
k[i].val=t;
}
sort(k,k+n,cmp);
for(int i=0; i<n; i++) {
printf("%d%c",k[i].id+1,i+1==n?'\n':' ');
}
}
return 0;
}
G题
找规律,这个变化可以保证 两个a,b一定可以消去,a,b,的位置可以交换,所以题目就变成了找两个字符串对应的,c ,左右两边的a,b奇偶是不是一样的。
1. 如果c个数不相等直接输出no;
2. 相等 判断 ,以c为分隔符的区间 a,b,的奇偶相不相等。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const long long mod=1e9+7;
const int maxn=1e4+25;
const int INF=0x7fffffff;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
struct two {
int x,y;
} k[maxn],k2[maxn];
int main() {
char a[maxn],b[maxn];
int flag,c;
while(~scanf("%s%s",&a,&b)) {
int la=strlen(a),lb=strlen(b);
memset(k,0,sizeof(k));
memset(k2,0,sizeof(k2));
c=0;
flag=1;
int pa,pb;
pa=pb=0;
for(int i=0; i<la; i++) {
if(a[i]=='a') {
k[pa].x=(k[pa].x+1)%2;
}
if(a[i]=='b') {
k[pa].y=(k[pa].y+1)%2;
}
if(a[i]=='c') {
pa++;
c++;
}
}
for(int i=0; i<lb; i++) {
if(b[i]=='a') {
k2[pb].x=(k2[pb].x+1)%2;
}
if(b[i]=='b') {
k2[pb].y=(k2[pb].y+1)%2;
}
if(b[i]=='c') {
pb++;
c--;
}
}
int l=max(pa,pb);
if(c!=0)flag=0;
for(int i=0; i<=l; i++) {
if(k[i].x!=k2[i].x||k[i].y!=k2[i].y) {
flag=0;
}
if(!flag)break;
}
if(flag)printf("Yes\n");
else printf("No\n");
}
return 0;
}
K题
就是一个找因子的题 2018 因子 1 ,2018 ,2 ,1009;
所以
1. 所有的 奇数可以和所有的 2018的倍数匹配。
2. 2018 可以和所有的数匹配,
3. 偶数 可以和所有 1009 的倍数匹配
4. 1009 可以和所有 偶数匹配;
注意一下,其中重复算的就行。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const long long mod=1e9+7;
const int maxn=2e5+25;
const int INF=0x7fffffff;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
int main() {
long long sum=0,a,b,c,d;
while(scanf("%lld%lld%lld%lld",&a,&b,&c,&d)!=EOF) {
sum=0;
long long x1,x2,x1009,x2018,y1,y2,y1009,y2018;
x2=x1=(b-a+1)/2;
if((b-a)%2==0) {
if(a&1)x1++;
else x2++;
}
x1009=(a%1009==0)+b/1009-a/1009;
x2018=(a%2018==0)+b/2018-a/2018;
y2=y1=(d-c+1)/2;
if((d-c)%2==0) {
if(c&1)y1++;
else y2++;
}
y1009=(c%1009==0)+d/1009-c/1009;
y2018=(c%2018==0)+d/2018-c/2018;
sum+=(x1-x1009+x2018)*y2018;
sum+=x2018*(y1+y2);
sum+=(x2-x2018)*(y1009);
sum+=(x1009-x2018)*y2;
printf("%lld\n",sum);
}
return 0;
}