zoukankan      html  css  js  c++  java
  • 2019icpc-徐州网络赛


    B. hxc写的

      AC code:

    #pragma GCC optimize(2)
    #include <cstdio>
    #include <queue>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <iostream>
    #include <iomanip>
    #include <cmath>
    #include <vector>
    #include <set>
    #include <map>
    #include <fstream>
    #include <cassert>
    #define ll long long
    #define R register int
    #define I inline void
    #define lc c[x][0]
    #define rc c[x][1]
    
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int maxn = 1e6 + 10;
    int n,q;
    
    inline int read()
    {
        int x=0,f=0; char ch=0;
        while(!isdigit(ch)) {f|=ch=='-';ch=getchar();}
        while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        return f?-x:x;
    }
    
    struct node
    {
        int num;
        int typ;
        int key;
        int ans;
    }pp[maxn];
    
    vector<int> v;
    
    int getid(int x)
    {
        return lower_bound(v.begin(),v.end(),x) - v.begin();
    }
    
    int con[maxn];
    int nxt[maxn];
    
    int cmp(node a,node b)
    {
        if(a.key != b.key)
            return a.key > b.key;
        return a.num < b.num;
    }
    
    int cmp1(node a,node b)
    {
        return a.num < b.num;
    }
    
    int find(int x)
    {
        if(x == nxt[x])
            return x;
        return nxt[x] = find(nxt[x]);
    }
    int u[maxn];
    
    int main()
    {
        n = read();
        q = read();
        for(int i = 1; i <= q; i++)
        {
            //pp[i].num = i;
            int a,b;
            a = read();
            b = read();
            pp[i].key = b;
            pp[i].typ = a;
            v.push_back(b);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        int len = v.size();
    
        //printf("len%d
    ",len);
        for(int i = 1; i <= len; i++)
        {
            nxt[i] = i;
            //printf("qwe%d
    ",v[i - 1]);
        }
    
        con[len - 1] = 0;
        for(int i = 0; i < len - 1; i++)
        {
            if(v[i] + 1 == v[i + 1])
                con[i + 1] = 1;
            //printf("con%d
    ",con[i]);
        }
    
        /*for(int i = 1; i <= len; i++)
            printf("%d %d
    ",v[i - 1],con[i]);
        printf("
    ");*/
    
        for(int i = 1; i <= q; i++)
        {
            int key = getid(pp[i].key) + 1;
            //printf("key%d %d
    ",pp[i].key,key);
            if(pp[i].typ == 1)
            {
                if(con[key])
                {
                    nxt[find(key)] = find(key + 1);
                }
                else
                {
                    int temp = find(key);
                    //printf("qwe%d
    ",find(key));
                    u[find(key)] = 1;
                    //printf("qwe%d
    ",find(key));
                }
            }
            else
            {
                if(u[find(key)] == 1)
                {
                    //printf("f%d
    ",nxt[key]);
                    if(v[find(key) - 1] + 1 <= n)
                        //pp[i].ans = v[find(key)] + 1;
                        printf("%d
    ",v[find(key) - 1] + 1);
                    else
                        //pp[i].ans = -1;
                        printf("-1
    ");
                }
                else
                {
                    //printf("124252
    ");
                    printf("%d
    ",v[find(key) - 1]);
                }
            }
        }
    
        /*for(int i = 1; i <= q; i++)
            if(pp[i].typ == 2)
            {
                printf("%d
    ",pp[i].ans);
            }*/
    }
    View Code

    C. Buy Watermelon

      题意:将体积为w的西瓜切成两半,保证两半的重量均为偶数。

      思路:水题,题意含糊不清。

      AC code:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    int w;
    
    int main(){
        scanf("%d",&w);
        if(w==2||w%2==1) printf("NO
    ");
        else printf("YES
    ");
        return 0;
    }
    View Code

    D. Carnegion(kmp)

      题意:化简题意即判断是否为子串。

      思路:kmp查找子串,时间复杂度O(q*(S+T))。

      AC code:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<assert.h>
    using namespace std;
    
    static int * GetNext(const char *sub)
    {
        int lensub = strlen(sub);
        int *next = (int *)malloc(lensub*sizeof(int));
        assert(next != NULL);
        next[0] = -1;
        next[1] = 0;
        int j = 1;
        int k = 0;
        while(j+1<lensub)
        {
            if((k==-1) || (sub[k]==sub[j]))
                next[++j] = ++k;
            else
                k = next[k];
        } 
        return next;
    }
    
    int KMP(const char *str,const char *sub,int pos)
    {
        assert(str!=NULL && sub!=NULL);
        int lenstr = strlen(str);
        int lensub = strlen(sub);
        if(pos<0 || pos>=lenstr)
            return -1;
        int *next = GetNext(sub);
        int i = pos;
        int j = 0;
        while(i<lenstr && j<lensub)
        {
            if(j==-1 || (str[i]==sub[j]))
                i++,j++;
            else
                j = next[j];
        }
        free(next);
        if(j >= lensub)
            return i-j;
        else
            return -1;
    }
    
    const int maxn=1e5+5;
    int m,len1,len2;
    char T[maxn],S[maxn];
    
    int main(){
        scanf("%s",T);
        len1=strlen(T);
        scanf("%d",&m);
        while(m--){
            scanf("%s",S);
            len2=strlen(S);
            if(len1>len2){
                if(KMP(T,S,0)>=0) printf("my child!
    ");
                else printf("oh, child!
    ");
            }
            else if(len1==len2){
                if(strcmp(T,S)==0) printf("jntm!
    ");
                else printf("friend!
    ");
            }
            else{
                if(KMP(S,T,0)>=0) printf("my teacher!
    ");
                else printf("senior!
    ");
            }
        }
        return 0;
    }
    View Code

    E. XKC‘s basketball(单调队列)

      题意:在长为5e5的数组中,对每一个a[i],求右边最后一个>=(a[i]+m)的下标。

      思路:lx写得。反向遍历,维护一个递增的队列,只进队不出队,如果当前a[i]<=que[end],那么不用进队,因为比a[i]大的数并且在i之后会屏蔽a[i]的作用; 当a[i]>que[end],则加入队尾。每次查询可以遍历得到que[begin]~que[end]中第一个>=a[i]+m的下标,当然也可以用二分加速。

      AC代码:

    #include <iostream>
    #include <cstdio>
    #include <stack>
    #include <map>
    using namespace std;
    
    inline int read()
    {
        int x=0,f=1;
        char ch = 0;
        while(!isdigit(ch))
        {
            if(ch=='-') f = -1;
            ch = getchar();
        }
        while(isdigit(ch))
        {
            x = x*10+ch-'0';
            ch = getchar();
        }
        return x*f;
    }
    int n,m;
    long long num[500050];
    int ans[500050];
    int dui[500050];
    int ed;
    int main()
    {
        n = read(), m = read();
        for(int i=1; i<=n; i++) num[i] = read();
        for(int i=n; i>=1; i--)
        {
            int you = 0;
            while(you<ed && num[i]+m>num[dui[you]]) you++;
            if(you>=ed)
            {
                ans[i] = -1;
                if(num[i]>num[dui[ed-1]])
                {
                    dui[ed] = i;
                    ed++;
                }
            }
            else
            {
                ans[i] = dui[you]-i-1;
            }
    
        }
        for(int i=1; i<=n; i++)
        {
            if(i>1) putchar(' ');
            printf("%d",ans[i]);
        }
        putchar('
    ');
        return 0;
    }
    View Code

    G. Colorful String(回文自动机)

      题意:求给定字串的所有回文子串的价值,字符串的价值定义为不同字符的个数。

      思路:回文自动机裸体。比赛现场学得回文自动机,用回文自动机求出所有种类的回文串的区间及其数量。然后用前缀记录计算得到所有回文子串的价值。

      AC code:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const int maxn=3e5+5;
    char s[maxn],s1[maxn];
    int n,p,q,fail[maxn],cnt[maxn],len[maxn],tot,last,ch[maxn][26],l[maxn],r[maxn];
    int pre[maxn][30],leng;
    LL ans;
    
    inline int newnode(int x){
        len[++tot]=x;
        return tot;
    }
    
    inline int getfail(int x,int n){
        while(s[n-len[x]-1]!=s[n]) x=fail[x];
        return x;
    }
    
    int main(){
        scanf("%s",s+1);
        leng=strlen(s+1);
        for(int i=1;i<=leng;++i)
            s1[i]=s[i];
        s[0]=-1,fail[0]=1,last=0;
        len[0]=0,len[1]=-1,tot=1;
        for(int i=1;s[i];++i){
            s[i]-='a';
            p=getfail(last,i);
            if(!ch[p][s[i]]){
                q=newnode(len[p]+2);
                l[q]=i-len[q]+1,r[q]=i;
                fail[q]=ch[getfail(fail[p],i)][s[i]];
                ch[p][s[i]]=q;
            }
            ++cnt[last=ch[p][s[i]]];
        }
        for(int i=tot;i;--i)
            cnt[fail[i]]+=cnt[i];
        for(int i=1;i<=leng;++i){
            for(int j=0;j<26;++j)
                pre[i][j]=pre[i-1][j];
            ++pre[i][s1[i]-'a'];
        }
        for(int i=tot;i;--i){
            int tmp=0;
            for(int j=0;j<26;++j)
                if(pre[r[i]][j]-pre[l[i]-1][j]>0) ++tmp;
            ans+=1LL*tmp*cnt[i];
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    K. Center(计算几何)

      题意:给n个点的点集,求最少加入多少个点使得所有点关于某个点成中心对称。

      思路:n^2枚举所有点对的中点,找到枚举次数最多的中心点,该点就是最合适的中心点,假设其出现次数为Max,该点为tmp,那么答案为(n-2*Max+mp1[tmp]),mp1用来记录原始点集中点的数量。为了方便处理,可以将初始点×2,这样中心点一定为整数点。

      AC code:

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #include<map>
    #include<utility>
    using namespace std;
    
    typedef pair<int,int> PII;
    const int maxn=1005;
    int n,Max;
    PII pt[maxn],tmp;
    map<PII,int> mp1,mp2;
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d%d",&pt[i].first,&pt[i].second);
            pt[i].first*=2,pt[i].second*=2;
            ++mp1[pt[i]];
        }
        for(int i=1;i<=n;++i)
            for(int j=i;j<=n;++j){
                PII t=make_pair((pt[i].first+pt[j].first)/2,(pt[i].second+pt[j].second)/2);
                ++mp2[t];
                if(mp2[t]>Max){
                    Max=mp2[t];
                    tmp=t;
                }
                else if(mp2[t]==Max){
                    if(mp1[t]<mp1[tmp])
                        tmp=t;
                }
            }
        printf("%d
    ",n-2*Max+mp1[tmp]);
        return 0;
    }
    View Code

    M. Longest subsequence(思维)

      题意:给定字符串s和t,求s中最长的子序列,且满足字典序大于t,输出子序列的长度,如果没有,输出-1。

      思路:比赛时没有思路。赛后补题。首先记录后缀,用aft[i][j]表示s[i]后面第一个j+’a‘的位置。然后对字符串t,枚举所求子序列从第j个字符开始大于t(前面j-1个字符与t保持一致)的情况,也就是找到pos右边第一个大于t[j]的下标x,从x开始全部选取,取答案最大值。注意子序列必须严格>t,前m个字符与t相同,之后再取后面的情况也可以。

      AC code:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    const int maxn=1e6+5;
    const int inf=0x3f3f3f3f;
    char s[maxn],t[maxn];
    int n,m,ans,aft[maxn][30],flag=1;
    
    int main(){
        scanf("%d%d",&n,&m);
        scanf("%s%s",s+1,t+1);
        for(int i=n-1;i>=0;--i){
            for(int j=0;j<26;++j)
                if(j==s[i+1]-'a') aft[i][j]=i+1;
                else aft[i][j]=aft[i+1][j];
        }
        int pos=0;
        for(int i=1;i<=m;++i){
            int tmp=t[i]-'a';
            for(int j=tmp+1;j<26;++j)
                if(aft[pos][j]) ans=max(ans,i+n-aft[pos][j]);
            pos=aft[pos][tmp];
            if(!pos){
                flag=0;
                break;
            }
        }
        if(flag&&pos!=n) ans=max(ans,m+n-pos);
        if(!ans) printf("-1
    ");
        else printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    获取设备的UUID
    关于获取基站信息总结
    【转】获取CID 和 LAC的方法
    js(javascript)与ios(Objective-C)相互通信交互
    ios面试题
    iOS 知识-常用小技巧大杂烩
    iOS时间格式的转换
    PresentViewController切换界面
    宏文件
    iOS使用NSMutableAttributedString 实现富文本(不同颜色字体、下划线等)
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11488463.html
Copyright © 2011-2022 走看看