• 【赛后总结+部分题解】2019中国大学生程序设计竞赛(CCPC)


    赛后总结:

      T:今天状态一般,甚至有点疲惫。然后12点比赛开始,和队友开始看题,从最后往前面看,发现数学题公式看不懂。然后发现队友已经双开做1001和1006了,我看着1007有人A,开始做1007。看了一会发现这是一个简单签到题,构造一下就完事了。然后一遍A,结束。在他们看1008的时候,我回去看1002和1003,1002的题意没看清楚,队友说的也有点模糊,然后不知道怎么下手。开始看1003,因为A的人真的好多呜呜呜。从AC自动机一直re转为后缀自动机,然后不会。结束了。今天对队伍的贡献太少了,复杂度也没算好,一直在re。做题策略还是有点问题,不该纠结自己不会的领域。然后也有很多不会的知识需要去弥补。

          P:lucky,从中间看到的第一题就是一道签到题。但由于读题不完整,在输出格式上WA了2-3次。所幸,过了。然后,就去看了钓鱼那题,将题意告诉了队友,队友有思路直接开做,我负责着错误样例。期间,我考虑到的一个点跟队友说,队友无法理解,我就想着自己打打看。AC后,才发现,队友这次想复杂了。接着的1002,1003,只能说自己的知识储备不够,大概从题目能够知道用了什么算法,但无法解决。

      J:今天状态贼差,1008WA了七八次还是没A出来,结果是我想复杂了,队友一下就A了,还是太弱了,1002是线段树,但是不知道该怎么做,看来应该做一下线段树专题了。

    部分题解:

    1001 ^&^

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<set>
    #include<cmath>
    #include<string>
    #include<map>
    #include<vector>
    #include<ctime>
    #include<stack>
    using namespace std;
    #define mm(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    const long long mod = 1e9 + 7;
    const int maxn = 1e6 + 10;
    
    int main()
    {
        ll a, b, c, k, cnt;
        int t;
        cin >> t;
        k = 1;
        while (t--)
        {
            c = 0, k = 1, cnt = 0;
            scanf("%lld%lld", &a, &b);
            int flag = 1;
            while (a || b)
            {
                if (a & 1 && b & 1)
                {
                    c += k;
                }
                else if ((a & 1) + (b & 1) == 1 && flag)
                {
                    flag = 0, cnt = k;
                }
                a >>= 1, b >>= 1;
                k <<= 1;
            }
            if (!c) c = cnt == 0 ? 1 : cnt;
            printf("%lld
    ", c);
        }
    }
    View Code

    1002 array

    题解来源:https://mmfunnytree.github.io/2019/08/23/begin14/#more?tdsourcetag=s_pcqq_aiomsg 原博主的代码有点点小问题,不能直接提交哦

    分析

      • 首先可以想到,由于一开始给的A数组是个排列,且第一种操作加的数字固定为1e7,所以,操作1可以认为在原序列中删除了A[i]A这个数字;
      • 那么我们可以把A[i]这个数字标记为已经被删除,那么下次查询的时候,一方面我们可以从原序列中去查询第一个大于等于k,且未在A[1..r]出现过的数字,另一方面,我们可以在标记删除的容器里二分找到第一个不小于k的数字,两者取小便可,根据排列的性质,这两个数字一定不会冲突;
      • 所以问题就变成了,维护一个set,存放被删除的数字,构造一个主席树,然后查询的时候直接找到第一个合适的数字便可。
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #pragma GCC optimize(2)
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<set>
    #include<cmath>
    #include<string>
    #include<map>
    #include<vector>
    #include<ctime>
    #include<stack>
    using namespace std;
    #define mm(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    const long long mod = 1e9+7;
    const int maxn = 2e5;
    set<int>st;
    int n,m,lst;
    int T[maxn],lson[maxn*20],rson[maxn*20],c[maxn*20],tot;
    int a[maxn];
    
    void update(int &u,int p,int l,int r)
    {
        ++tot;
        lson[tot]=lson[u];
        rson[tot]=rson[u];
        c[tot]=c[u]+1;
        u=tot;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(p<=mid) update(lson[u],p,l,mid);
        else update(rson[u],p,mid+1,r);
    }
    
    int tmp1;
    void query(int rt,int L,int R,int l,int r)
    {
        if(tmp1<n+1) return;
        if(L<=l&&R>=r)
        {
            if(c[rt]==0)
            {
                tmp1=l;return;
            }
            if(c[rt]==r-l+1) return;
            int mid=(l+r)>>1;
            if(c[lson[rt]]==mid-l+1) query(rson[rt],L,R,mid+1,r);
            else query(lson[rt],L,R,l,mid);
        }
        int mid=(l+r)>>1;
        if(L<=mid) query(lson[rt],L,R,l,mid);
        if(R>mid) query(rson[rt],L,R,mid+1,r);
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            st.clear();
            tot=1;lst=0;
            scanf("%d %d",&n,&m);
            st.insert(n+1);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                T[i]=T[i-1];
                update(T[i],a[i],1,n);
            }
            int op,pos,r,k;
            while(m--)
            {
                scanf("%d",&op);
                if(op==1)
                {
                    scanf("%d",&pos);
                    pos^=lst;
                    st.insert(a[pos]);
                }
                else
                {
                    scanf("%d %d",&r,&k);
                    r^=lst,k^=lst;
                    int ans=*(st.lower_bound(k));
                    tmp1=n+1;
                    query(T[r],k,n,1,n);
                    ans=min(ans,tmp1);
                    printf("%d
    ",ans);
                    lst=ans;
                }
            }
        }
        return 0;
    }

    1003 K-th occurrence

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #pragma GCC optimize(2)
    #include <bits/stdc++.h>
    using namespace std;
    #define mm(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    const long long mod = 998244353;
    const int maxn = 1e5+5;
    const int inf = 0x3f3f3f3f;
    char s[maxn];
    struct Tree{
        int tot, rt[maxn], lson[maxn*20], rson[maxn*20], cnt[maxn*20];
        int build (int l, int r) {
            int o = ++tot;
            int mid = (l + r) >> 1;
            cnt[o] = 0;
            if (l != r) {
                lson[o] = build(l, mid);
                rson[o] = build(mid+1, r);
            }
            return o;
        }
        int update(int prev, int l, int r, int v) {
            int o = ++tot;
            int mid = (l + r) >> 1;
            lson[o] = lson[prev];
            rson[o] = rson[prev];
            cnt[o] = cnt[prev] + 1;
            if (l != r) {
                if (v <= mid) lson[o] = update(lson[o], l, mid, v);
                else rson[o] = update(rson[o], mid+1, r, v);
            }
            return o;
        }
        int query(int u, int v, int l, int r, int k) {
            if (l == r) return l;
            int mid = (l + r) >> 1;
            int num = cnt[lson[v]] - cnt[lson[u]];
            if (num >= k) return query(lson[u], lson[v], l, mid, k);
            else return query(rson[u], rson[v], mid+1, r, k-num);
        }
    };
    struct SuffixArray{ // 下标1
        int cntA[maxn], cntB[maxn], A[maxn], B[maxn];
        int Sa[maxn], tsa[maxn], height[maxn], Rank[maxn]; // Sa[i] 排名第i的下标, Rank[i] 下标i的排名
        int n, dp[maxn][18];
        Tree T;
        void build() {
            T.tot = 0;
            T.rt[0] = T.build(1, n);
            for (int i = 1; i <= n; ++i) T.rt[i] = T.update(T.rt[i-1], 1, n, Sa[i]);
        }
        void init(char *buf, int len) { // 预处理,sa,rank,height
            n = len;
            for (int i = 0; i < 128; ++i) cntA[i] = 0;
            for (int i = 1; i <= n; ++i) cntA[(int)buf[i]]++;
            for (int i = 1; i < 128; ++i) cntA[i] += cntA[i-1];
            for (int i = n; i >= 1; --i) Sa[ cntA[(int)buf[i]]-- ] = i;
            Rank[ Sa[1] ] = 1;
            for (int i = 2; i <= n; ++i) {
                Rank[Sa[i]] = Rank[Sa[i-1]];
                if (buf[Sa[i]] != buf[Sa[i-1]]) Rank[Sa[i]]++;
            }
            for (int l = 1; Rank[Sa[n]] < n; l <<= 1) {
                for (int i = 0; i <= n; ++i) cntA[i] = 0;
                for (int i = 0; i <= n; ++i) cntB[i] = 0;
                for (int i = 1; i <= n; ++i) {
                    cntA[ A[i] = Rank[i] ]++;
                    cntB[ B[i] = (i + l <= n) ? Rank[i+l] : 0]++;
                }
                for (int i = 1; i <= n; ++i) cntB[i] += cntB[i-1];
                for (int i = n; i >= 1; --i) tsa[ cntB[B[i]]-- ] = i;
                for (int i = 1; i <= n; ++i) cntA[i] += cntA[i-1];
                for (int i = n; i >= 1; --i) Sa[ cntA[A[tsa[i]]]-- ] = tsa[i];
                Rank[ Sa[1] ] = 1;
                for (int i = 2; i <= n; ++i) {
                    Rank[Sa[i]] = Rank[Sa[i-1]];
                    if (A[Sa[i]] != A[Sa[i-1]] || B[Sa[i]] != B[Sa[i-1]]) Rank[Sa[i]]++;
                }
            }
            for (int i = 1, j = 0; i <= n; ++i) {
                if (j) --j;
                int tmp = Sa[Rank[i] - 1];
                while (i + j <= n && tmp + j <= n && buf[i+j] == buf[tmp+j]) ++j;
                height[Rank[i]] = j;
            }
        }
        void st() {
            for (int i = 1; i <= n; ++i) {
                dp[i][0] = height[i];
            }
            for (int j = 1; j <= log2(n); ++j) {
                for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
                    dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
                }
            }
        }
        int rmq(int l, int r) {
            if (l == r) return inf;
            l++;
            int len = r - l + 1;
            int x = log2(len);
            return min(dp[l][x], dp[r - (1 << x) + 1][x]);
        }
        int findl(int pos, int len) {
            int l = 1, r = pos;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (rmq(mid, pos) < len) l = mid + 1;
                else r = mid - 1;
            }
            return l;
        }
        int findr(int pos, int len) {
            int l = pos, r = n;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (rmq(pos, mid) < len) r = mid - 1;
                else l = mid + 1;
            }
            return r;
        }
        int solve(int ql, int qr, int k) {
            int len = qr - ql + 1;
            int pos = Rank[ql];
            int l = findl(pos, len);
            int r = findr(pos, len);
            if (r - l + 1 < k) return -1;
            return T.query(T.rt[l-1], T.rt[r], 1, n, k);
        }
    }S;
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,m;
            scanf("%d %d",&n,&m);
            scanf("%s",s+1);
            S.init(s,strlen(s+1));
            S.st();
            S.build();
            int l,r,k;
            for(int i=0;i<m;i++)
            {
                scanf("%d %d %d",&l,&r,&k);
                printf("%d
    ",S.solve(l,r,k));
            }
        }
        return 0;
    }
    View Code

    1006 Shuffle Card

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<string>
    #include<map>
    #include<vector>
    #include<ctime>
    #include<stack>
    #include<fstream>
    #include<iomanip>
    using namespace std;
    #define mm(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 1e5+10;
    const int inf = 0x3f3f3f3f;
    const int mod = 998244353;
    const double PI = acos(-1.0);
    int a[maxn];
    int b[maxn];
    map<int,int> ma;
    int main(){
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%d",a+i);
        for(int i=0;i<m;i++)
            scanf("%d",b+i);
        for(int i=m-1;i>=0;i--){
            if(ma[b[i]])
                b[i]=0;
            else
                ma[b[i]]=1;
        }
        int sum=0;
        for(int i=m-1;i>=0;i--){
            if(b[i]!=0){
                printf("%d ",b[i]);
                sum++;
            }
            if(sum==n)
                break;
        }
        if(sum!=n){
            for(int i=0;i<n;i++){
                if(!ma[a[i]]){
                    printf("%d ",a[i]);
                    sum++;
                }
                if(sum==n)
                    break;
            }
        }
        return 0;
    }
    View Code

    1007 Windows of CCPC

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #pragma GCC optimize(2)
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<set>
    #include<cmath>
    #include<string>
    #include<map>
    #include<vector>
    #include<ctime>
    #include<stack>
    using namespace std;
    #define mm(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    const long long mod = 1e9+7;
    const int maxn = 2e5;
    char mp[2000][2000];
    int num[20];
    void init()
    {
        num[0]=1;
        for(int i=1;i<=10;i++)
        {
            num[i]=num[i-1]*2;
        }
        mp[1][1]='C';
        mp[1][2]='C';
        mp[2][1]='P';
        mp[2][2]='C';
        for(int i=2;i<=10;i++)
        {
            for(int j=1;j<=num[i];j++)
            {
                for(int k=1;k<=num[i];k++)
                {
                    if(j<=num[i-1]&&k<=num[i-1])
                        continue;
    
                    if(k>num[i-1]&&j<=num[i-1])
                    {
                        mp[j][k]=mp[j][k-num[i-1]];
                    }
                    else if(j>num[i-1]&&k>num[i-1])
                    {
                        mp[j][k]=mp[j-num[i-1]][k-num[i-1]];
                    }
                    else if(j>num[i-1]&&k<=num[i-1])
                    {
                        if(mp[j-num[i-1]][k]=='C')
                            mp[j][k]='P';
                        else mp[j][k]='C';
                    }
                }
            }
        }
    }
    
    int main()
    {
        init();
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int k;
            scanf("%d",&k);
            for(int i=1;i<=num[k];i++)
            {
                for(int j=1;j<=num[k];j++)
                {
                    printf("%c",mp[i][j]);
                }
                printf("
    ");
            }
        }
    //
    
    
    
    
        return 0;
    }
    View Code

    1008Fishing Master

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<set>
    #include<cmath>
    #include<string>
    #include<map>
    #include<vector>
    #include<ctime>
    #include<stack>
    using namespace std;
    #define mm(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    const long long mod = 1e9 + 7;
    const int maxn = 1e6 + 10;
    int t, n, vis[maxn];
    ll a[maxn], k;
    struct node{
        int id;
        ll yu;
    }extra[maxn];
    bool cmp(node a,node b) {
        return a.yu>b.yu;
    }
    int main()
    {
        ll ans = 0, cnt, sum;
        cin >> t;
        while (t--)
        {
            queue<ll>q;
            ans = 0;
            cnt = 1;
            sum = 0;
            scanf("%d%lld", &n, &k);
            ans+=k;
            for (int i = 0; i < n; ++i)
            {
                scanf("%lld", &a[i]);
                cnt+=a[i]/k;
                extra[i].id=i;
                extra[i].yu=a[i]%k;
                ans+=a[i];
            }
            if(cnt<n){
                sort(extra,extra+n,cmp);
                for(ll i=0;i<=n-cnt-1;i++){
                        ans+=k-extra[i].yu;
                }
            }
            printf("%lld
    ",ans);
        }
    }
    View Code
  • 相关阅读:
    免费linux远程主机nitrousIO
    利用PyWapFetion发免费天气短信
    接口中的 sort排序 + md5加密
    即点即改心得
    js判断客户端访问是安卓还是ios
    php将时间戳转换成几小时前的格式封装
    前端请求接口出现的跨域问题
    使用redis技术实现注册登录列表以及关注功能
    windows下的redis安装以及扩展安装
    Yii2 学习心得
  • 原文地址:https://www.cnblogs.com/Tangent-1231/p/11401965.html
Copyright © 2020-2023  润新知