[Helvetic Coding Contest 2017 online mirror]
来自FallDream的博客,未经允许,请勿转载,谢谢,
第一次在cf上打acm...和同校大佬组队打
总共15题,比较鬼畜,最后勉强过了10题。
AB一样的题目,不同数据范围,一起讲吧
你有一个背包,最多装k本书,你在第i天需要拥有一本编号ai的书,但是你可以去商店购买并加入背包。
问你至少要买多少本书?n,k<=400000
显然可以贪心,留下下一次需要的时间最早的书就行了。
- #include<iostream>
- #include<cstdio>
- #include<queue>
- #define pa pair<int,int>
- #define mp(x,y) make_pair(x,y)
- #define INF 2000000000
- #define MN 400000
- using namespace std;
- inline int read()
- {
- int x = , f = ; char ch = getchar();
- while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
- while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
- return x * f;
- }
- priority_queue<pa> q;
- int n,k,a[MN+],ne[MN+],la[MN+],ans=;
- bool in[MN+];
- int main()
- {
- n=read();k=read();
- for(int i=;i<=n;++i) a[i]=read();
- for(int i=n;i;--i)
- {
- ne[i]=la[a[i]]?la[a[i]]:INF;
- la[a[i]]=i;
- }
- for(int i=;i<=n;++i)
- {
- if(in[a[i]])
- ++k,q.push(mp(ne[i],a[i]));
- else
- {
- ++ans;
- while(q.size()==k) in[q.top().second]=,q.pop();
- q.push(mp(ne[i],a[i]));
- in[a[i]]=;
- }
- }
- cout<<ans;
- return ;
- }
C. 还是同样的题面,只不过每本书要的钱不一样了,n,k<=80
把一本书留到下一次用看作一个区间覆盖,发现这就是一道k可重区间问题,费用流建图即可
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #define S 0
- #define MN 80
- #define T 81
- #define INF 2000000000
- using namespace std;
- inline int read()
- {
- int x = , f = ; char ch = getchar();
- while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
- while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
- return x * f;
- }
- int d[MN+],n,k,head[MN+],cnt=,a[MN+],c[MN+],ans=,pi=,la[MN+];
- struct edge{int to,next,w,c;}e[MN*MN];
- bool inq[MN+],mark[MN+];
- deque<int> q;
- inline void ins(int f,int t,int w,int c)
- {
- e[++cnt]=(edge){t,head[f],w,c}; head[f]=cnt;
- e[++cnt]=(edge){f,head[t],,-c};head[t]=cnt;
- }
- bool modlabel()
- {
- for(int i=S;i<=T;++i) d[i]=INF;
- d[T]=;inq[T]=;q.push_front(T);
- while(!q.empty())
- {
- int x=q.front();q.pop_front();
- for(int i=head[x];i;i=e[i].next)
- if(e[i^].w&&e[i^].c+d[x]<d[e[i].to])
- {
- d[e[i].to]=d[x]+e[i^].c;
- if(!inq[e[i].to])
- {
- inq[e[i].to]=;
- if(d[e[i].to]<d[q.size()?q.front():]) q.push_front(e[i].to);
- else q.push_back(e[i].to);
- }
- }
- inq[x]=;
- }
- for(int i=S;i<=T;++i)
- for(int j=head[i];j;j=e[j].next)
- e[j].c+=d[e[j].to]-d[i];
- return pi+=d[S],d[S]<INF;
- }
- int dfs(int x,int f)
- {
- if(x==T) return ans+=pi*f,f;
- int used=;mark[x]=;
- for(int i=head[x];i;i=e[i].next)
- if(e[i].w&&!e[i].c&&!mark[e[i].to])
- {
- int w=dfs(e[i].to,min(f-used,e[i].w));
- used+=w;e[i].w-=w;e[i^].w+=w;
- if(used==f) return used;
- }
- return used;
- }
- int main()
- {
- n=read();k=read()-;
- for(int i=;i<=n;++i) a[i]=read();
- for(int i=;i<=n;++i) c[i]=read();
- for(int i=;i<=n;++i) ans+=c[a[i]];
- ins(S,,k,);ins(n,T,k,);
- for(int i=;i<n;++i) ins(i,i+,INF,);
- for(int i=;i<=n;++i)
- {
- if(la[a[i]])
- {
- if(la[a[i]]==i-) ans-=c[a[i]];
- else ins(la[a[i]]+,i,,-c[a[i]]);
- }
- la[a[i]]=i;
- }
- while(modlabel())
- do memset(mark,,sizeof(mark));
- while(dfs(S,INF));
- cout<<ans;
- return ;
- }
DEF比较牛逼 D题wa了个几十次,还剩半分钟的时候居然过了 感觉这种奇奇怪怪的题并没有发言权...
G题是送分的
H题
给你一个数字n(<=1000000),要求你构造两个字符串,使得第二个字符串作为子序列在第一个字符串中的出现次数恰好是n次,且第一个字符串的长度不超过200
考虑用组合数来解决。让第二个串为'aaaaab',那么第一个串中每个B的贡献都是他前面的a的个数选出5个的组合数。只要选择适当的地方插入就行了。
- #include<iostream>
- #include<cstdio>
- #define MN 50
- using namespace std;
- inline int read()
- {
- int x = , f = ; char ch = getchar();
- while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
- while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
- return x * f;
- }
- int num[MN+],n,C[MN+][];
- int main()
- {
- n=read();C[][]=;
- for(int i=;i<=MN;++i)
- {
- C[i][]=;
- for(int j=;j<=;++j)
- C[i][j]=C[i-][j]+C[i-][j-];
- }
- for(int i=MN;i>=;--i)
- while(n>=C[i][]) n-=C[i][],++num[i];
- for(int i=;i<=MN;putchar('a'),++i)
- for(int j=;j<=num[i];++j) putchar('b');
- printf(" aaaaab");
- return ;
- }
I
给定一个长度为n字符串,求每个不同子串的出现次数的平方。
T(T<=10)组数据,n<=100000
建出后缀自动机之后,简单dp一下就行了。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- using namespace std;
- inline int read()
- {
- int x = , f = ; char ch = getchar();
- while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
- while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
- return x * f;
- }
- int c[][],step[],fail[];
- long long val[];long long sum[];
- char s[];
- int cnt=,last=,n;
- void ins(int x)
- {
- int p=last,np=++cnt;step[np]=step[last]+;val[np]=;
- for(;p&&!c[p][x];p=fail[p])c[p][x]=np;
- if(!p)fail[np]=;
- else
- {
- int q=c[p][x];
- if(step[q]==step[p]+) fail[np]=q;
- else
- {
- int nq=++cnt;step[nq]=step[p]+;
- for(int i=;i<;i++)c[nq][i]=c[q][i];
- fail[nq]=fail[q];fail[q]=fail[np]=nq;
- for(;c[p][x]==q;p=fail[p])c[p][x]=nq;
- }
- }
- last=np;
- }
- int v[],rk[];
- void work()
- {
- memset(v,,sizeof(v));
- for(int i=;i<=cnt;i++)v[step[i]]++;
- for(int i=;i<=n;i++)v[i]+=v[i-];
- for(int i=cnt;i;i--) rk[v[step[i]]--]=i;
- for(int i=cnt;i;i--) val[fail[rk[i]]]+=val[rk[i]];
- }
- bool vis[];
- long long Dfs(int x)
- {
- if(vis[x]) return sum[x];
- if(x!=)sum[x]=1LL*val[x]*val[x];vis[x]=;
- for(int i=;i<;++i) if(c[x][i])
- sum[x]+=Dfs(c[x][i]);
- return sum[x];
- }
- int main()
- {
- for(int T=read();T;--T)
- {
- memset(c,,sizeof(c));
- memset(fail,,sizeof(fail));
- memset(step,,sizeof(step));
- memset(vis,,sizeof(vis));
- memset(sum,,sizeof(sum));
- memset(val,,sizeof(val));
- cnt=last=;
- scanf("%s",s+);n=strlen(s+);
- for(int i=;s[i];ins(s[i++]-'a'));
- work();
- cout<<Dfs()<<endl;
- }
- return ;
- }
J是送分的
K
给定一棵树,有边权,你要从1号点出发,要求每个点经过次数不超过k的前提下,经过的边的权值和最大(多次经过只算一次)
n<=100000
显然是一道树形dp,用f[i]表示回到i号点的最大答案,f2[i]表示不回来的最大答案,然后用优先队列保存前k大就行了。
- #include<iostream>
- #include<cstdio>
- #include<queue>
- #define mp(x,y) make_pair(x,y)
- #define pa pair<int,int>
- #define MN 100000
- using namespace std;
- inline int read()
- {
- int x = , f = ; char ch = getchar();
- while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
- while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
- return x * f;
- }
- int n,k,cnt=,f[MN+],f2[MN+],head[MN+],mark[MN+];
- struct edge{int to,next,w;}e[MN*+];
- priority_queue<pa,vector<pa>,greater<pa> > q[MN+],q2[MN+];
- inline void ins(int f,int t,int w)
- {
- e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
- e[++cnt]=(edge){f,head[t],w};head[t]=cnt;
- }
- void Dp(int x,int fa)
- {
- for(int i=head[x];i;i=e[i].next)
- if(e[i].to!=fa)
- {
- Dp(e[i].to,x);
- q[x].push(mp(f[e[i].to]+e[i].w,e[i].to));
- }
- int mx=,mx2=,mm;
- while(q[x].size()>k) q[x].pop();
- if(q[x].size()==k) mm=q[x].top().first,mark[q[x].top().second]=x; else mm=;
- while(q[x].size()>k-) q[x].pop();
- while(!q[x].empty())
- {
- pa now=q[x].top();
- f[x]+=now.first;
- mark[now.second]=x;
- q[x].pop();
- }
- for(int i=head[x];i;i=e[i].next)
- if(e[i].to!=fa)
- {
- if(mark[e[i].to]==x)
- mx=max(mx,f2[e[i].to]-f[e[i].to]);
- else mx2=max(mx2,e[i].w+f2[e[i].to]);
- }
- f2[x]=max(f[x],max(f[x]+mx2,f[x]+mx+mm));
- }
- int main()
- {
- n=read();k=read();
- for(int i=;i<n;++i)
- {
- int x=read()+,y=read()+,w=read();
- ins(x,y,w);
- }
- Dp(,);
- printf("%d\n",max(f[],f2[]));
- return ;
- }
M
给样例猜题意,输出前k小的数字的和就行了。
N
给定两个长度为n的序列,你要从每个序列中选出k个,并且满足a序列中选出的第i个的位置小等于从b序列中选出的第i个,求最小的和。
n<=2000
考虑二分一个值,并把所有数字减去那个值,通过n^2dp求出最小的情况下最多/最少选出多少个,区间包含了k时输出答案即可
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #define ll long long
- #define MN 2200
- using namespace std;
- inline int read()
- {
- int x = , f = ; char ch = getchar();
- while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
- while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
- return x * f;
- }
- ll f[MN+][MN+],N[MN+][MN+],N2[MN+][MN+];
- int a[MN+],b[MN+],n,k;
- int main()
- {
- n=read();k=read();
- for(int i=;i<=n;++i) a[i]=read();
- for(int i=;i<=n;++i) b[i]=read();
- int l=-(1e9),r=1e9,mid;
- while(l<=r)
- {
- mid=1LL*l+r>>;
- memset(f,,sizeof(f));
- for(int i=;i<=n;++i) f[][i]=f[i][]=;
- for(int i=;i<=n;++i)
- for(int j=i;j<=n;++j)
- {
- if(f[i-][j]<f[i][j]) f[i][j]=f[i-][j],N[i][j]=N[i-][j],N2[i][j]=N2[i-][j];
- else if(f[i-][j]==f[i][j]) N[i][j]=max(N[i][j],N[i-][j]),N2[i][j]=min(N2[i][j],N2[i-][j]);
- if(f[i][j-]<f[i][j]) f[i][j]=f[i][j-],N[i][j]=N[i][j-],N2[i][j]=N2[i][j-];
- else if(f[i][j-]==f[i][j]) N[i][j]=max(N[i][j],N[i][j-]),N2[i][j]=min(N2[i][j],N2[i][j-]);
- if(f[i-][j-]+a[i]-mid+b[j]-mid<f[i][j])
- f[i][j]=f[i-][j-]+a[i]-mid+b[j]-mid,N[i][j]=N[i-][j-]+,N2[i][j]=N2[i-][j-]+;
- else if(f[i-][j-]+a[i]-mid+b[j]-mid==f[i][j])
- N[i][j]=max(N[i][j],N[i-][j-]+),N2[i][j]=min(N2[i][j],N2[i-][j-]+);
- }
- if(N[n][n]>=k&&N2[n][n]<=k) return *printf("%lld",f[n][n]+2LL*k*mid);
- else if(N[n][n]>k) r=mid-;
- else l=mid+;
- }
- return ;
- }
O题意相同 数据范围500000
发现这就像一个二分图匹配,并且每个b之和之前的a连边,考虑二分之后用堆来贪心。
从前往后确定每一个b的匹配,往堆里加入a,这个b只能和堆顶配对,如果更优秀的话就配对。但是这可能不是最优的,所以之后还要加入-b来表示推流,更换一个b和这个a配对。
- #include<iostream>
- #include<cstdio>
- #include<queue>
- #define ll long long
- #define mp(x,y) make_pair(x,y)
- #define pa pair<ll,int>
- #define MN 500000
- using namespace std;
- inline int read()
- {
- int x = ; char ch = getchar();
- while(ch < '' || ch > '') ch = getchar();
- while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
- return x;
- }
- int A[MN+],B[MN+],n,m;ll tot;
- priority_queue<pa,vector<pa>,greater<pa> > q;
- int Solve(int x)
- {
- tot=;int num=;
- for(int i=;i<=n;++i)
- {
- q.push(mp(A[i],));
- ll t=q.top().first,now=B[i]-x;
- if(now+t<)
- {
- tot+=now+t;
- q.pop();
- q.push(mp(-now,));
- }
- }
- while(!q.empty()) num+=q.top().second,q.pop();
- return num;
- }
- int main()
- {
- n=read();m=read();
- for(int i=;i<=n;++i) A[i]=read();
- for(int i=;i<=n;++i) B[i]=read();
- int l=,r=2e9,mid;
- while(l<=r)
- {
- mid=1LL*l+r>>;int num=Solve(mid);
- if(num==m) return *printf("%lld\n",tot+1LL*m*mid);
- if(num<m) l=mid+;
- else r=mid-;
- }
- return ;
- }
[Helvetic Coding Contest 2017 online mirror]的更多相关文章
- 【Codeforces】Helvetic Coding Contest 2017 online mirror比赛记
第一次打ACM赛制的团队赛,感觉还行: 好吧主要是切水题: 开场先挑着做五道EASY,他们分给我D题,woc什么玩意,还泊松分布,我连题都读不懂好吗! 果断弃掉了,换了M和J,然后切掉了,看N题: l ...
- Helvetic Coding Contest 2017 online mirror (teams allowed, unrated)
G. Fake News (easy) time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Helvetic Coding Contest 2017 online mirror (teams allowed, unrated) J
Description Heidi's friend Jenny is asking Heidi to deliver an important letter to one of their comm ...
- Helvetic Coding Contest 2017 online mirror (teams allowed, unrated) M
Description The marmots have prepared a very easy problem for this year's HC2 – this one. It involve ...
- Helvetic Coding Contest 2017 online mirror (teams allowed, unrated) A
Description Your search for Heidi is over – you finally found her at a library, dressed up as a huma ...
- Helvetic Coding Contest 2019 online mirror (teams allowed, unrated)
http://codeforces.com/contest/1184 A1 找一对整数,使x^x+2xy+x+1=r 变换成一个分式,保证整除 #include<iostream> #in ...
- CF 690C3. Brain Network (hard) from Helvetic Coding Contest 2016 online mirror (teams, unrated)
题目描述 Brain Network (hard) 这个问题就是给出一个不断加边的树,保证每一次加边之后都只有一个连通块(每一次连的点都是之前出现过的),问每一次加边之后树的直径. 算法 每一次增加一 ...
- Helvetic Coding Contest 2016 online mirror A1
Description Tonight is brain dinner night and all zombies will gather together to scarf down some de ...
- Helvetic Coding Contest 2016 online mirror F1
Description Heidi has finally found the mythical Tree of Life – a legendary combinatorial structure ...
随机推荐
- visualVM使用jstatd和jmx连接远程jvm及遇到的问题解决
visualVM使用jstatd和jmx连接远程jvm及遇到的问题解决 JMX方式: 编辑Tomact里bin目录的catalina.sh . 在其头部加入 JAVA_OPTS=" -Dco ...
- react中的DOM操作
前面的话 某些情况下需要在典型数据流外强制修改子代.要修改的子代可以是 React 组件实例,也可以是 DOM 元素.这时就要用到refs来操作DOM 使用场景 下面是几个适合使用 refs 的情况 ...
- 职场选择之大公司 VS 小公司
其实这是个非常难回答的问题,很多职场新人都会有类似的顾虑和疑问. 这个问题就好比业界比较容易引起争议的编程语言哪个是最好的一样.大公司还是小公司里面发展,只有身处其中才能体会,如人饮水,冷暖自知. 笔 ...
- Django REST framework+Vue 打造生鲜超市(一)
一.项目介绍 1.1.掌握的技术 Vue + Django Rest Framework 前后端分离技术 彻底玩转restful api 开发流程 Django Rest Framework 的功能实 ...
- 你考虑清楚了吗就决定用 Bootstrap ?
近年来,在前端项目中, Bootstrap 已经成为了一个非常受欢迎的工具. Bootstrap 的确有很多优点,然而,如果你的团队中恰好有一个专职的前端工程师.那我推荐你们不要使用 Bootstra ...
- Spark快速入门
Spark 快速入门 本教程快速介绍了Spark的使用. 首先我们介绍了通过Spark 交互式shell调用API( Python或者scala代码),然后演示如何使用Java, Scala或者P ...
- spring-oauth-server实践:使用授权方式四:client_credentials 模式下access_token做业务!!!
spring-oauth-server入门(1-10)使用授权方式四:client_credentials 模式下access_token做业务!!! 准备工作 授权方式四::客户端方式: 服务网关地 ...
- nginx和nfs
1.安装nginx #yum install epel-release -y #yum install nginx -y #vim /usr/local/nginx/conf/nginx.conf - ...
- AtCoder Beginner Contest 073
D - joisino's travel Time Limit: 2 sec / Memory Limit: 256 MB Score : 400400 points Problem Statemen ...
- Typescript学习
一 什么是Typescript 简单的说,TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持,它由 Microsoft 开发,代码开源于 GitHub ...