2018湖南嘉杰杯ACM省赛
目录
I、买一送一
H、千万别用树套树
F、Use FFT
I、买一送一
theme:n个商店,标号1~n,每个商店卖标号为ai的商品(不同店可能卖相同商品),给出这些商店间的单向连接关系,求从商店1走到商店i(2<=i<=n),在两不同的店各买一个商品的二元组的不同(x,y)个数f(i)。
solution:首先要清楚这是一个图论题。先用临街表存点和边。由题意可知发f(i)=f(i-1)+curCnt-preCnt;即将f(i)分解为第二个商品在商店i买和不在商店i买两种情况,不在则为f(i-1),在则为以1到n的某条路径中不相同商品作为第一个购买商品,即curCnt,又在该条路径上可能已存在商品ai了,这时就要相应减去以上一个ai作为第二个商品的个数,即preCnt。
模型其实是以结点1为根节点的一棵树,所以编号i可能在树上不止一个结点,出现次数取决于从1到i的路径条数。所以结果加起来即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define far(i,t,n) for(int i=t;i<n;++i)vector<int>v[100010];
int a[100010];
ll ans[100010];
int vis[100010];
int h[100010];
int tot;void dfs(int t)
{for(int i=0;i<v[t].size();++i){int x=v[t][i];ans[x]=ans[t]+tot-h[a[x]];int pre=h[a[x]];h[a[x]]=tot;int flag=0;if(!vis[a[x]])tot++,flag=1;vis[a[x]]++;dfs(x);h[a[x]]=pre;if(flag)tot--;vis[a[x]]--;}
}int main()
{int n;while(~scanf("%d",&n)){for(int i=1;i<=n;++i)v[i].clear();memset(a,0,sizeof(a));memset(ans,0,sizeof(ans));memset(vis,0,sizeof(vis));memset(h,0,sizeof(h));for(int i=2;i<=n;++i){int x;scanf("%d",&x);v[x].push_back(i);}for(int i=1;i<=n;++i)scanf("%d",&a[i]);tot=1;vis[a[1]]=1;dfs(1);for(int i=2;i<=n;++i)printf("%lld\n",ans[i]);}return 0;
}
/*
3
1 2
1 2 3
3
1 1
1 2 3
4
1 2 3
1 3 2 3
*/
H、千万别用树套树
theme:q次操作,每次要么插入一条端点在[l,r]的线段,要么查询包含[l,r],(即端点[x,y]满足x<=l<=r<=y)的线段条数。其中查询时满足r-l<=2
solution:对于插入操作,则把[l,r]区间内的每个顶点的值(a[i])+1,对于查询,当r-l==0时,条数为a[l];当r-l==1时,条数为a[l]-e[l],e[l]表示以l为终点的条数;当r-l==2时,条数为a[l+1]-e[l+1]-s[l+1]+eq[l+1],s[l]表示以l为起点的条数,eq[i]为同时以i为起点与终点的线段。
注意:插入[l,l]时,a[l]只加一次!
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define far(i,t,n) for(int i=t;i<n;++i)const int SIZE=100010;
ll t[4*SIZE];
ll bj[4*SIZE];ll s[100010];
ll e[100010];
ll eq[100010];void updata(int k,int l,int r)
{int mid=(l+r)>>1;//cout<<"updata: "<<bj[k]<<" ";t[k<<1]+=(mid-l+1)*bj[k];t[(k<<1)+1]+=(r-mid)*bj[k];bj[k<<1]+=bj[k];bj[(k<<1)+1]+=bj[k];bj[k]=0;//cout<<"updata: "<<bj[k<<1]<<" "<<bj[(k<<1)+1]<<endl;
}void add(int root,int s,int e,int delta,int l,int r)
{if(s<=l&&e>=r){t[root]+=(r-l+1)*delta;bj[root]+=delta;return;}if(bj[root])updata(root,l,r);int mid=(l+r)>>1;if(s<=mid)add(root<<1,s,e,delta,l,mid);if(e>mid)add((root<<1)+1,s,e,delta,mid+1,r);t[root]=t[root<<1]+t[(root<<1)+1];//cout<<"t[]"<<root<<": "<<t[root]<<endl;
}ll query(int root,int i,int j,int l,int r)//i,j为要查询的区域
{if(i<=l&&j>=r)return t[root];//cout<<bj[root]<<endl;if(bj[root])updata(root,l,r);//cout<<root<<" "<<bj[root<<1]<<" "<<bj[(root<<1)+1]<<endl;int mid=(l+r)>>1;ll m1=0,m2=0;if(i<=mid)m1=query(root<<1,i,j,l,mid);if(j>mid)m2=query((root<<1)+1,i,j,mid+1,r);return m1+m2;
}int main()
{int n,q;while(~scanf("%d%d",&n,&q)){memset(t,0,sizeof(t));memset(bj,0,sizeof(bj));memset(s,0,sizeof(s));memset(e,0,sizeof(e));memset(eq,0,sizeof(eq));int t,l,r;for(int i=0;i<q;++i){scanf("%d%d%d",&t,&l,&r);if(t==1){add(1,l,r,1,1,n);s[l]++;e[r]++;if(l==r)eq[l]++;}else{if(r-l==0)printf("%lld\n",query(1,l,l,1,n));else if(r-l==1)printf("%lld\n",query(1,l,l,1,n)-e[l]);elseprintf("%lld\n",query(1,l+1,l+1,1,n)-s[l+1]-e[l+1]+eq[l+1]);}}}return 0;
}
/*
4 100
1 3 3
1 1 4
1 3 3
1 2 3
1 3 4
1 1 3
1 2 4
*/
F、Use FFT
theme:给定两多项式P(x)=a0 + a1x + … + anxn 与 Q(x)=b0 + b1x + … + bmxm. 可求得:P(x)⋅Q(x)=c0 + c1x + … + cn + mxn + m 。给定 L 与 R.求 (cL + cL + 1 + … + cR) modulo (109 + 7) 。
solution:由多项式想乘性质,我们可以遍历a,对于每一个ai,找b中哪个区间的数与ai相加值在[l,r]范围内,所以问题转化为:1、求每一个ai在b中满足条件的区间[si,ei];2、求b中任意区间和(用前缀和)3、求ai*sum(b[s[i]],b[e[i]])。时间空间复杂度都为o(n)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define far(i,t,n) for(int i=t;i<n;++i)ll a[500010];
ll b[500010];
ll s[500010];
ll e[500010];
ll sum[500010];const ll mod=1e9+7;int main()
{int n,m,l,r;while(~scanf("%d%d%d%d",&n,&m,&l,&r)){far(i,0,n+1)scanf("%lld",&a[i]);far(i,0,m+1)scanf("%lld",&b[i]);sum[0]=b[0]%mod;far(i,1,m+1)sum[i]=(sum[i-1]+b[i])%mod;far(i,0,n+1){int li=l-i;int ri=r-i;if(ri<0){s[i]=e[i]=-1;continue;}if(ri<m)s[i]=li,e[i]=ri;else if(m<li)s[i]=e[i]=-1;elses[i]=li,e[i]=m;if(s[i]<0)s[i]=-1;}ll ans=0;far(i,0,n+1){int st=s[i],en=e[i];ll cnt;if(en==-1)continue;if(st==0||st==-1)cnt=sum[en];elsecnt=(sum[en]-sum[st-1]+mod)%mod;ans=(ans+ (a[i]%mod*cnt)%mod) %mod;}printf("%lld\n",ans);}return 0;
}
D:卖萌表情
//✔48ms(1000ms)
/*theme:已知以下 4 种都是卖萌表情(空白的部分可以是任意字符。竖线是便于展示的分隔符,没有实际意义):^ ^ | ^ | < | >v | v v | > | <| | < | >
(多组)给出n行m列的字符矩阵,找出互不重叠的卖萌表情数量的最大值.互不重叠的意思是每个字符只属于至多一个卖萌表情。
1≤n,m≤1000,矩阵只包含 ^, v, <, > 4 种字符.n × m 的和不超过 2×10^6.
*
*
*
*
*
solution:可分为两组分开算(左边两种和右边两种互不影响),由于遍历时从左上开始,右边两种没有冲突情况,所以只需遍历求个数即可
而左边两种可能存在^<^<^<^<^最优解,因为遍历是是以'^'为基准找下一行'v'匹配,但 ^ 比^ ^的'v'更靠左,即对v的利用率越高<v<v<v<v< v v v
由贪心思想,应优先考虑第二种再选第一种,注意选中后要标记为已选(可改为其他符号),避免重复
*/#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;char a[1100][1100];
int n,m;int solve1()
{int cnt=0;for(int i=0;i<n-1;++i)for(int j=0;j<m-1;++j)if(a[i][j]=='^'){if(j-1>=0&&a[i+1][j-1]=='v'&&a[i+1][j+1]=='v')++cnt,a[i+1][j-1]='0',a[i+1][j+1]='0';else if(j+2<m&&a[i][j+2]=='^'&&a[i+1][j+1]=='v')++cnt,a[i][j+2]='0',a[i+1][j+1]='0';}return cnt;
}int solve2()
{int cnt=0;for(int i=0;i<n-2;++i)for(int j=0;j<m;++j)if(a[i][j]=='<'){if(i+2<n&&j<m-1&&a[i+1][j+1]=='>'&&a[i+2][j]=='<')++cnt,a[i+1][j+1]='0',a[i+2][j]='0';}else if(a[i][j]=='>'){if(i+2<n&&a[i+1][j-1]=='<'&&a[i+2][j]=='>')++cnt,a[i+1][j-1]='0',a[i+2][j]='0';}return cnt;}int main()
{while(~scanf("%d%d",&n,&m)){for(int i=0;i<n;++i)scanf("%s",a[i]);//for(int i=0;i<n;++i)
// printf("%s",a[i]),putchar('\n');int ans1=solve1();int ans2=solve2();
//cout<<ans1<<" "<<ans2<<endl;int ans=ans1+ans2;printf("%d\n",ans);}
}/*
2 4
^^^^
>vv<
2 4
vvvv
>^^<
4 2
v>
<>
<>
^>
3 4
^>^>
<v>v
>>>>
2 9
^<^<^<^<^
<v<v<v<v<2
0
2
2
3
*/
2018湖南嘉杰杯ACM省赛相关推荐
- 2018湖南省第十四届“嘉杰杯”大学生计算机程序设计竞赛总结
经过三个月的幸苦练习,在省赛这个大舞台上,我们小队收获了一枚铜牌. 从一开始刷南阳oj八十道水题,vj上的二十场校赛,再到多校的场场自闭,CF的熬夜作战.嗯,我确实付出了很多.然而我始终在思考,我这么 ...
- 湖南省第十四届“嘉杰杯”大学生计算机程序设计大赛 总结
初次现场赛感受 通过这次比赛发现自己和大佬们的差距还很大,此次 做出题目六题以上基本是一等奖了,我们队伍做出了三个题,拿铜. 这次比赛也是我们大一时候第一次参加大型ACM赛事.之所以是现在(2018. ...
- 2018第九届蓝桥杯个人赛省赛(软件类)C++A组试题第九题
一[题目描述] 标题:倍数问题 [题目描述] 众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数.但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼.现在小葱给了你 n 个数,希 ...
- 2014湖南农业大学ACM校赛
湖南农业大学 2014年 ACM 校赛Problem 2014 /2/23 星期日 12:30-17:30 A.搜素 1794.查找指定的字符串 B.链表 1795 ...
- XTU 1235 CQRXLB 2015嘉杰信息杯 湘潭赛
最近一直在看博弈,今天早上一直都在看Nim博弈,虽然对相关的结论已经了解了很多,但是其实深入的内在知识并不是很理解,直到后来看到了如何寻找平衡态. 然后,上个月去湖南湘潭参加2015嘉杰信息杯比赛的时 ...
- 华为杯大学生计算机软件大赛,关于举办2018年西安电子科技大学程序设计网络赛暨第十六届“华为杯”大学生程序设计竞赛的通知...
各学院: 程序设计是大学生运用计算机充分展示自己分析问题和解决问题能力的一个重要途径,对于培养大学生实践能力.团队意识.创新意识.顽强意志和综合素质具有显著作用和效果.为了推动这项创新性素质教育活动的 ...
- 记2020年(第16届)湖南ACM省赛
记2020年(第16届)湖南ACM省赛 写在前面 我很喜欢<龙族>里那个叫路明非的衰小孩.虽然我也不知道为什么要说这个,逃 这个世界有多大,取决于你认识的人,你每认识一个人,世界对你来说就 ...
- 2018第九届蓝桥杯大赛软件类B组C/C++省赛题解
2018第九届蓝桥杯大赛软件类B组C/C++省赛目录 试题 A:第几天(结果填空) 试题 B:明码(结果填空) 试题 C:乘积尾0(结果填空) 试题 D:测试次数(结果填空) 试题 E:快速排序(结果 ...
- 2021暨南大学轩辕杯ACM程序设计新生赛题解
title : 2021暨南大学轩辕杯ACM程序设计新生赛 date : 2021-12-12 tags : ACM,练习记录 author : Linno 题目链接:https://ac.nowco ...
最新文章
- 通过微信公众号获取用户信息(java版)
- vector简单实现
- boost::log模块实现logging旋转文本文件的示例
- QT的QMediaPlayer类的使用
- NSIS打包软件(一)
- mongodump 备份还原
- 550什么意思_布草知识 | 都是羽绒,为什么价格大不同?
- 深入理解JavaScript系列(12):变量对象(Variable Object)
- datagrip替换字_Datagrip 快捷键和常用插件持续更新一集一些使用技巧
- C++11 static_assert
- Table控件布局DataList模板
- C#集成FastDFS断点续传
- access统计行数 vb_VB代码行数统计工具
- 华为数通笔记-NQA
- ZEMAX | 照明设计中实用的光学模拟方法
- 2019年BET公司面试题目大汇总
- Python之Scikit-Learm
- ARM920T内核工作模式
- 每天学一点flash(78) flash cs5.5 加载 jpeg-xr 格式
- MP4文件批量转码成MP3