[Atcoder Grand Contest 001] Tutorial
Link:
A:
……
#include <bits/stdc++.h> using namespace std;
long long res=;
int n,dat[]; int main()
{
scanf("%d",&n);
for(int i=;i<=*n;i++) scanf("%d",&dat[i]);
sort(dat+,dat+*n+);
for(int i=;i<=*n;i+=) res+=dat[i];
printf("%lld",res);
return ;
}
Problem A
B:
结论题,然后我还推了个假结论……
并不太知道能怎么提升,估计多做做就好了吧
官方题解的图没怎么看懂……结论为$3*(n-gcd(n,k))$
#include <bits/stdc++.h> using namespace std;
typedef long long ll;
ll n,k;
ll gcd(ll a,ll b){return (a%b==)?b:gcd(b,a%b);} int main()
{
scanf("%lld%lld",&n,&k);
printf("%lld",*(n-gcd(n,k)));
return ;
}
Problem B
C:
求要删去多少个点才能保证树的直径小于$k$
我一开始直接找树的重心,以为复杂度能把其他人的碾过去……
但实际上,树的直径的中点与树的重心无直接关系(如扫把型的树)
正解是树形$dp$或直接分类讨论:
设化简后的图为$G$,
1、如果$k$为偶数,则$G$中必有一点$v$使得所有$dist(v,x)\le k/2$
2、如果$k$为奇数,则$G$中必有一边$e$使得所有$dist(e,x)/le (k-1)/2$
这样的点$v$、边$e$才是树的直径的中心!
接下来只要枚举每个点/每条边作为树的直径的中心,取包含点的最大值即可
#include <bits/stdc++.h> using namespace std;
const int MAXN=;
struct edge{int to,nxt;}e[MAXN<<];
int n,k,x,y,head[MAXN],dist[MAXN],tot=,tmp=,res=,S=; void add_edge(int from,int to)
{
e[++tot].nxt=head[from];e[tot].to=to;head[from]=tot;
e[++tot].nxt=head[to];e[tot].to=from;head[to]=tot;
} int dfs(int x,int anc,int lmt)
{
int ret=;if(x==S) dist[x]=;
for(int i=head[x];i;i=e[i].nxt)
{
if(e[i].to==anc) continue;
dist[e[i].to]=dist[x]+;
if(dist[e[i].to]<=lmt) ret+=dfs(e[i].to,x,lmt);
}
return ret;
} int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<n;i++)
scanf("%d%d",&x,&y),add_edge(x,y); for(int i=;i<=n;i++)
res=max(res,dfs(S=i,,k/));
if(!(k&)) return printf("%d",n-res),; for(int i=;i<=n;i++)
for(int j=head[i];j;j=e[j].nxt)
res=max(res,dfs(S=i,e[j].to,(k-)>>)+dfs(S=e[j].to,i,(k-)>>));
printf("%d",n-res);
return ;
}
Problem C
注意,如果直径为奇数,其中心为一条边!
D:
构造题+推结论
可以将回文串中的对应点连边,目标是使得所有点连通
如果A串中有$a$个奇数,B串中有$b$个奇数,为保证连通则至少要有$n-1$条边:
$由(n-a)/2+(n-b)/2\ge n-1 可得 a+b\le 2$
因此,只可能$a=1,b=1$或$a=2,b=0$或$a=0,b=2$,其它情况均无解
最后只要对这两种情况找到一种普遍构造即可
#include <bits/stdc++.h> using namespace std;
const int MAXN=1e5+;
int n,m,dat[MAXN],o1,o2,st; int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++) scanf("%d",&dat[i]);
for(int i=;i<=m;i++)
if(dat[i]&)
if(!o1) o1=i;
else if(!o2) o2=i;
else return puts("Impossible"),; if(o1) swap(dat[],dat[o1]);
if(o2) swap(dat[m],dat[o2]);
for(int i=;i<=m;i++) printf("%d ",dat[i]); if(m==) m++;
dat[]--;dat[m]++;st=dat[]?:;
printf("\n%d\n",m-st+);
for(int i=st;i<=m;i++) printf("%d ",dat[i]);
return ;
}
Problem D
此题将字符回文串转化为图论问题的思路值得借鉴
E:
要求$\sum C(a_i+b_i+a_j+b_j,a_i+a_j)$
发现数的范围只有2000,将每个组合数映射至$(-a_i,-b_i)-(a_j,b_j)$的路径条数!
这样每个终点的值就是其它所有点到其的路径和,即组合数的和!最后减去自己出发的贡献即可
#include <bits/stdc++.h> using namespace std;
typedef long long ll;
const int MAXN=2e5+,MAXM=<<,MOD=1e9+;
ll res,fac[MAXM],inv[MAXM],dp[MAXM][MAXM],ret;
int n,a[MAXN],b[MAXN],mx,mx_sum; ll quick_pow(ll a,ll b)
{
for(ret=;b;b>>=,(a*=a)%=MOD)
if(b&) (ret*=a)%=MOD;
return ret;
} ll C(ll a,ll b)
{return fac[a]*inv[a-b]%MOD*inv[b]%MOD;} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d%d",&a[i],&b[i]),
mx=max(mx,max(a[i],b[i])),mx_sum=max(mx_sum,a[i]+b[i]); for(int i=;i<=n;i++)
dp[-a[i]+mx][-b[i]+mx]++;
for(int i=;i<=(mx<<);i++)
for(int j=;j<=(mx<<);j++)
if(dp[i][j]) (dp[i+][j]+=dp[i][j])%=MOD,(dp[i][j+]+=dp[i][j])%=MOD;
for(int i=;i<=n;i++) (res+=dp[a[i]+mx][b[i]+mx])%=MOD; mx_sum<<=;fac[]=;
for(int i=;i<=mx_sum;i++) fac[i]=fac[i-]*i%MOD;
inv[mx_sum]=quick_pow(fac[mx_sum],MOD-);
for(int i=mx_sum;i;i--) inv[i-]=inv[i]*i%MOD; for(int i=;i<=n;i++)
res=(res-C((a[i]+b[i])<<,a[i]<<)+MOD)%MOD;
res=(res*(MOD+)>>)%MOD;
printf("%lld",res);
return ;
}
Problem E
F:
将模型转化,明显可转化为使得从1到n每个数位置的字典序最小
也就是让$pos[a[i]]=i$,只能将相邻的差大于$k$的位置交换,求最小字典序
对于该问题,将相对位置不会改变的$|pos_i-pos_j|<k$的$i,j$相连
那么最终结果即为该$DAG$的最小拓扑序
为了缩减建图的复杂度,发现这样的偏序关系具有传递性,不用将所有关系都直接相连,可只连最近边
从后往前对于每个$i$,用线段树找到在$[pos[i]-k+1,pos[i]]$和$[pos[i],pos[i]+k-1]$中最近的$j$连边即可
#include <bits/stdc++.h> using namespace std;
#define X first
#define Y second
#define mid ((l+r)>>1)
#define lc k<<1,l,mid
#define rc k<<1|1,mid+1,r
#define pb push_back
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=5e5+,INF=<<;
struct edge{int nxt,to;}e[MAXN<<];
int head[MAXN],tot;
int n,k,in[MAXN],a[MAXN],pos[MAXN],seg[MAXN<<]; void add_edge(int x,int y)
{e[++tot]=(edge){head[x],y};head[x]=tot;in[y]++;}
void Update(int pos,int val,int k,int l,int r)
{
seg[k]=min(seg[k],val);
if(l==r) return;//最后一层也要先更新再返回!
if(pos<=mid) Update(pos,val,lc);
else Update(pos,val,rc);
}
void Query(int &mn,int a,int b,int k,int l,int r)
{
if(a<=l&&r<=b)
{mn=min(mn,seg[k]);return;}
if(a<=mid) Query(mn,a,b,lc);
if(b>mid) Query(mn,a,b,rc);
} int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
scanf("%d",&a[i]),pos[a[i]]=i;
for(int i=;i<=*n;i++) seg[i]=INF;
for(int i=n;i>=;i--)
{
int nxt=INF,pre=INF;
//注意询问必须保证与[1,n]相交
Query(nxt,pos[i],pos[i]+k-,,,n);
Query(pre,pos[i]-k+,pos[i],,,n);
if(nxt!=INF) add_edge(pos[i],pos[nxt]);
if(pre!=INF) add_edge(pos[i],pos[pre]);
Update(pos[i],i,,,n);
} priority_queue<int,vector<int>,greater<int> > q;
for(int i=;i<=n;i++)
if(!in[i]) q.push(i);
for(int i=;i<=n;i++)
{
int t=q.top();q.pop();
pos[i]=t;
for(int j=head[t];j;j=e[j].nxt)
if(!(--in[e[j].to])) q.push(e[j].to);
}
for(int i=;i<=n;i++) a[pos[i]]=i;
for(int i=;i<=n;i++) printf("%d\n",a[i]);
return ;
}
Problem F
Tip:线段树都能写挂……
1、注意最后一层的更新
2、要保证询问区间和$[1,n]$有交!
[Atcoder Grand Contest 001] Tutorial的更多相关文章
- AtCoder Grand Contest 001 C Shorten Diameter 树的直径知识
链接:http://agc001.contest.atcoder.jp/tasks/agc001_c 题解(官方): We use the following well-known fact abou ...
- AtCoder Grand Contest 001 D - Arrays and Palindrome
题目传送门:https://agc001.contest.atcoder.jp/tasks/agc001_d 题目大意: 现要求你构造两个序列\(a,b\),满足: \(a\)序列中数字总和为\(N\ ...
- [Atcoder Grand Contest 004] Tutorial
Link: AGC004 传送门 A: …… #include <bits/stdc++.h> using namespace std; long long a,b,c; int main ...
- Atcoder Grand Contest 001 D - Arrays and Palindrome(构造)
Atcoder 题面传送门 洛谷题面传送门 又是道思维题,又是道把我搞自闭的题. 首先考虑对于固定的 \(a_1,a_2,\dots,a_n;b_1,b_2,\dots,b_m\) 怎样判定是否合法, ...
- Atcoder Grand Contest 001 F - Wide Swap(拓扑排序)
Atcoder 题面传送门 & 洛谷题面传送门 咦?鸽子 tzc 来补题解了?奇迹奇迹( 首先考虑什么样的排列可以得到.我们考虑 \(p\) 的逆排列 \(q\),那么每次操作的过程从逆排列的 ...
- AtCoder Grand Contest 001
B - Mysterious Light 题意:从一个正三角形边上一点出发,遇到边和已走过的边则反弹,问最终路径长度 思路:GCD 数据爆long long #pragma comment(linke ...
- [Atcoder Grand Contest 003] Tutorial
Link: AGC003 传送门 A: 判断如果一个方向有,其相反方向有没有即可 #include <bits/stdc++.h> using namespace std; ]; map& ...
- [Atcoder Grand Contest 002] Tutorial
Link: AGC002 传送门 A: …… #include <bits/stdc++.h> using namespace std; int a,b; int main() { sca ...
- AtCoder Grand Contest 001 题解
传送门 \(A\) 咕咕咕 const int N=505; int a[N],n,res; int main(){ scanf("%d",&n); fp(i,1,n< ...
随机推荐
- boost::algorithm用法详解之字符串关系判断
http://blog.csdn.net/qingzai_/article/details/44417937 下面先列举几个常用的: #define i_end_with boost::iends_w ...
- Hadoop NameNode元数据相关文件目录解析
在<Hadoop NameNode元数据相关文件目录解析>文章中提到NameNode的$dfs.namenode.name.dir/current/文件夹的几个文件: 1 current/ ...
- centos7 mysql cluster集群搭建基于docker
1.准备 mn:集群管理服务器用于管理集群的其他节点.我们可以从管理节点创建和配置集群上的新节点.重新启动.删除或备份节点. db2/db3:这是节点间同步和数据复制的过程发生的层. db4/db5: ...
- vue+koa+mysql简易demo
功能支持网址收藏编辑 代码: https://github.com/lanleilin/lanOdyssey/tree/master/vueKoa/webCollection1 运行方法: 在serv ...
- maven在add dependecy时搜索不出jar包的解决办法
一:前言 其实我一直都很头疼maven的项目管理的,因为觉得用起来还是没有那么方便的啊,不过今天我自己算是小弄了下maven项目的故那里,是一个同事在配置maven的项目,我去凑了下热闹而已,现在自己 ...
- java JDK动态代理的机制
一:前言 自己在稳固spring的一些特性的时候在网上看到了遮掩的一句话“利用接口的方式,spring aop将默认通过JDK的动态代理来实现代理类,不适用接口时spring aop将使用通过cgli ...
- 【Foreign】无聊的计算姬 [Lucas][BSGS]
无聊的计算姬 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 6 2 2 3 4 3 2 ...
- [POJ2406&POJ1961]用KMP解决字符串的循环问题两例
翻阅了一下网上资料,发现大部分都说这题是找规律...或是说YY出的一个算法..不会证明... 然后就脑补了一下证明 ~ 结论:对于一个字符串S[1..N],如果N mod (N-next[N])=0 ...
- [转载]超赞!32款扁平化Photoshop PSD UI工具包(下)
32款扁平化风格的UI工具包第二弹!上篇为大家分享了16款风格各异的UI Kits,下篇继续为大家呈上16款精美的UI工具包,全部都有Photoshop PSD文件可以下载哦,喜欢就赶紧收藏吧! 17 ...
- shell浅谈之三for、while、until循环【转】
转自:http://blog.csdn.net/taiyang1987912/article/details/38929069 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[- ...