2019icpc-徐州网络赛

Posted frankchen831x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",len);
    for(int i = 1; i <= len; i++)
    
        nxt[i] = i;
        //printf("qwe%d\n",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\n",con[i]);
    

    /*for(int i = 1; i <= len; i++)
        printf("%d %d\n",v[i - 1],con[i]);
    printf("\n");*/

    for(int i = 1; i <= q; i++)
    
        int key = getid(pp[i].key) + 1;
        //printf("key%d %d\n",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\n",find(key));
                u[find(key)] = 1;
                //printf("qwe%d\n",find(key));
            
        
        else
        
            if(u[find(key)] == 1)
            
                //printf("f%d\n",nxt[key]);
                if(v[find(key) - 1] + 1 <= n)
                    //pp[i].ans = v[find(key)] + 1;
                    printf("%d\n",v[find(key) - 1] + 1);
                else
                    //pp[i].ans = -1;
                    printf("-1\n");
            
            else
            
                //printf("124252\n");
                printf("%d\n",v[find(key) - 1]);
            
        
    

    /*for(int i = 1; i <= q; i++)
        if(pp[i].typ == 2)
        
            printf("%d\n",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\n");
    else printf("YES\n");
    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!\n");
            else printf("oh, child!\n");
        
        else if(len1==len2)
            if(strcmp(T,S)==0) printf("jntm!\n");
            else printf("friend!\n");
        
        else
            if(KMP(S,T,0)>=0) printf("my teacher!\n");
            else printf("senior!\n");
        
    
    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(\n);
    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\n",ans);
    return 0;
View Code

 


 

 

K. Center(计算几何)

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

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

  AC 吃哦的:

技术图片
#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",n-2*Max+mp1[tmp]);
    return 0;
View Code

 

以上是关于2019icpc-徐州网络赛的主要内容,如果未能解决你的问题,请参考以下文章

ICPC 2018 徐州赛区网络赛

ACM-ICPC 2018 徐州赛区(网络赛)

2018ICPC徐州区域赛网络赛G(vector+set模拟)

Trace 2018徐州icpc网络赛 思维+二分

ICPC2018徐州网络赛 Hard to prepare(dp)

Ryuji doesn't want to study 2018徐州icpc网络赛 树状数组