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