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); */
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;
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;
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;
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;
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;
以上是关于2019icpc-徐州网络赛的主要内容,如果未能解决你的问题,请参考以下文章
2018ICPC徐州区域赛网络赛G(vector+set模拟)