【賽後總結+部分題解】2019中國大學生程序設計競賽(CCPC) - 網絡選拔賽

賽後總結:php

  T:今天狀態通常,甚至有點疲憊。而後12點比賽開始,和隊友開始看題,從最後往前面看,發現數學題公式看不懂。而後發現隊友已經雙開作1001和1006了,我看着1007有人A,開始作1007。看了一會發現這是一個簡單簽到題,構造一下就完事了。而後一遍A,結束。在他們看1008的時候,我回去看1002和1003,1002的題意沒看清楚,隊友說的也有點模糊,而後不知道怎麼下手。開始看1003,由於A的人真的好多嗚嗚嗚。從AC自動機一直re轉爲後綴自動機,而後不會。結束了。今天對隊伍的貢獻太少了,複雜度也沒算好,一直在re。作題策略仍是有點問題,不應糾結本身不會的領域。而後也有不少不會的知識須要去彌補。node

      P:lucky,從中間看到的第一題就是一道簽到題。但因爲讀題不完整,在輸出格式上WA了2-3次。所幸,過了。而後,就去看了釣魚那題,將題意告訴了隊友,隊友有思路直接開作,我負責着錯誤樣例。期間,我考慮到的一個點跟隊友說,隊友沒法理解,我就想着本身打打看。AC後,才發現,隊友此次想複雜了。接着的1002,1003,只能說本身的知識儲備不夠,大概從題目可以知道用了什麼算法,但沒法解決。ios

  J:今天狀態賊差,1008WA了七八次仍是沒A出來,結果是我想複雜了,隊友一下就A了,仍是太弱了,1002是線段樹,可是不知道該怎麼作,看來應該作一下線段樹專題了。c++

 

部分題解:git

1001 ^&^github

#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\n", 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\n",ans);
                lst=ans;
            }
        }
    }
    return 0;
}

1003 K-th occurrenceide

#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\n",S.solve(l,r,k));
        }
    }
    return 0;
}
View Code

 

1006 Shuffle Cardui

#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("\n");
        }
    }
//




    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\n",ans);
    }
}
View Code
相關文章
相關標籤/搜索