AtCoder Grand Contest 006 题解
\(A\)
咕咕
const int N=105;
char s[N],t[N];int n;
inline bool eq(R int k){fp(i,1,k)if(s[n-k+i]!=t[i])return false;return true;}
int main(){
scanf("%d%s%s",&n,s+1,t+1);
fd(k,n,0)if(eq(k))return printf("%d\n",(n<<1)-k),0;
return 233;
}
\(B\)
把\(x\)放在最中间,然后在它左边放一个比它大的数,右边放两个比它小的数就行了
具体证明在\(D\)题里
const int N=5e5+5;
int vis[N],st[N],a[N],top,n,x;
int main(){
scanf("%d%d",&n,&x);
if(x==1||x==(n<<1)-1)return puts("No"),0;
puts("Yes");
if(x!=2){
a[n]=x,a[n-1]=x+1,a[n+1]=x-1,a[n+2]=x-2;
vis[x]=vis[x+1]=vis[x-1]=vis[x-2]=1;
}else{
a[n]=x,a[n-1]=x-1,a[n+1]=x+1,a[n+2]=x+2;
vis[x]=vis[x-1]=vis[x+1]=vis[x+2]=1;
}
fp(i,1,(n<<1)-1)if(!vis[i])st[++top]=i;
fp(i,1,n-2)a[i]=st[top--];
fp(i,n+3,(n<<1)-1)a[i]=st[top--];
fp(i,1,(n<<1)-1)printf("%d\n",a[i]);
return 0;
}
\(C\)
首先,假设操作的数为\(i\),左右分别为\(x,y\),那么操作之后的期望位置为\((2x-i+2y-i)/2=x+y-i\)
设\(a_i\)为原数组的差分数组,那么一次操作之后等价于交换\(a_i,a_{i+1}\)
因为\(m\)次操作等价于一个轮换,所以把轮换中的每个循环找出来就行了
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
const int N=1e5+5;
int a[N],id[N],sz[N],bl[N],to[N],nid[N],n,m;ll sum[N],k;
vector<int>st[N];
inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n);
fp(i,1,n)scanf("%d",&a[i]);
fd(i,n,1)a[i]-=a[i-1],id[i]=i;
scanf("%d%lld",&m,&k);
for(R int i=1,x;i<=m;++i)scanf("%d",&x),swap(id[x],id[x+1]);
fp(i,1,n)to[id[i]]=i;
fp(i,1,n)if(!bl[i]){
bl[i]=i,++sz[i];
for(R int j=to[i];j!=i;j=to[j])bl[j]=i,++sz[i];
st[i].resize(sz[i]),st[i][0]=i,nid[i]=0;
for(R int j=to[i],c=1;j!=i;j=to[j],++c)st[i][c]=j,nid[j]=c;
}
fp(i,1,n)sum[st[bl[i]][(k+nid[i])%sz[bl[i]]]]=a[i];
fp(i,1,n)sum[i]+=sum[i-1];
fp(i,1,n)printf("%lld\n",sum[i]);
return 0;
}
\(D\)
首先二分答案,把大于等于\(mid\)的记为\(1\),其余的记为\(0\),那么就转化为判断顶上是\(0/1\)
先判断两种特殊情况,\(101010.....101\),顶上必定为\(1\),\(0101010....010\),顶上必定为\(0\)
为了方便把边界去掉,也就是说看成一个\(n\)行\(2n-1\)列的网格,最终查询第一行第\(n\)列的值
发现有如下性质
\(1.\)假设有一段极长的全为\(0/1\)的段,记为\([l,r]\),且\(l\neq r\),那么上面所有行中\([l,r]\)这几列将一直为\(0/1\)
\(2.\)假设有一段极长的\(0/1\)相间的段,记为\([l,r]\),且\(l\neq r\),那么最终会在上面的某一行形成以\(p\)为分界的两个区间\([l,p]\)和\([p+1,r]\),且两个区间都满足性质\(1\)(\(p\)的位置取决于这个区间的奇偶性)
综上,最终所有区间都会形成满足性质\(1\)的区间,只要\(O(n)\)求出所有区间的右端点,即可查询最终第一行第\(n\)列的值为\(0/1\)了
综上,总复杂度为\(O(n\log n)\)
ps:这里也就可以说明\(B\)的正确性了,只要找到一组使得\(mid=x\)时顶上为\(1\)且\(mid=x+1\)时顶上为\(0\)的解即可
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=5e5+5;
int a[N],b[N],st[N],col[N],n,t,l,r,mid,ans;
bool ck(){
fp(i,1,n)b[i]=a[i]>=mid;
R int top=0;bool fl1=1,fl2=1;
fp(i,1,n)fl1&=(b[i]==(i&1)),fl2&=(b[i]!=(i&1));
if(fl1)return true;if(fl2)return false;
for(R int l=1,r=2;r<=n;l=r++){
if(b[r]==b[l]){
while(r+1<=n&&b[r+1]==b[l])++r;
st[++top]=r,col[top]=b[l];
}else{
while(r+1<=n&&((r+1-l)&1)==(b[r+1]^b[l]))++r;
if((r-l+1)&1)st[++top]=r,col[top]=b[l];
else st[++top]=(l+r)>>1,col[top]=b[l],st[++top]=r,col[top]=b[r];
}
}
assert(top);
fp(i,1,top)if(st[i-1]<=t&&st[i]>=t)return col[i];
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n),t=n,n=(n<<1)-1;
fp(i,1,n)scanf("%d",&a[i]);
l=2,r=n-1;
while(l<=r){
mid=(l+r)>>1;
ck()?(ans=mid,l=mid+1):r=mid-1;
}
printf("%d\n",ans);
return 0;
}
\(E\)
为什么我什么题都不会啊
首先,我们发现同一列的三个数永远在同一列,且只会有正序和逆序两种情况,不妨分别记为\(i\)和\(-i\)
其次,一次操作可以看成是把三个数取反,并交换间隔的两个数
那么我们把操作拆开来,一个是交换相隔的两个数(交换的过程中包括取反),一个是把某个数取反
交换相隔的数,我们显然可以把奇偶分开考虑
那么现在问题转化成给定一个排列,要把它变为有序,每一次可以交换相邻的两个数,求每一个数要交换多少次
这个可以贪心,即先把最大的搞到最后,再把次大的搞到最后……
那么每个数取反的次数,只要根据原来的情况和要交换的情况判断一下就好了
最后回到原问题,我们发现奇数的一次交换对应于偶数的一次取反
所以奇数的交换总次数要与偶数的取反总次数奇偶性相等
同理偶数的交换总次数也要和奇数的交换总次数相等
总复杂度\(O(n\log n)\)
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=1e5+5;
int n,a[N],b[N],c[N],f[N],g[N],id[N];
struct BIT{
int c[N];
inline void clr(){memset(c,0,(n+1)<<2);}
inline void upd(R int x,R int y){for(;x<=n;x+=x&-x)c[x]+=y;}
inline int query(R int x){R int res=0;for(;x;x-=x&-x)res+=c[x];return res;}
}t1,t2;
bool ck(){
fp(i,1,n){
id[i]=(a[i]-1)/3+1;
if((i&1)!=(id[i]&1))return false;
R int x=(id[i]-1)*3+1,y=(id[i]-1)*3+2,z=(id[i]-1)*3+3;
if(a[i]==x&&b[i]==y&&c[i]==z){g[i]=(n<<1);continue;}
if(a[i]==z&&b[i]==y&&c[i]==x){g[i]=(n<<1|1);continue;}
return false;
}
return true;
}
int main(){
scanf("%d",&n);
fp(i,1,n)scanf("%d",&a[i]);
fp(i,1,n)scanf("%d",&b[i]);
fp(i,1,n)scanf("%d",&c[i]);
if(!ck())return puts("No"),0;
for(R int i=1;i<=n;i+=2)t1.upd(i,1);
for(R int i=n-(n&1^1);i>0;i-=2){
f[i]=t1.query(n)-t1.query(id[i])+t2.query(id[i]-1);
t1.upd(id[i],-1),t2.upd(id[i],1);
}
t1.clr(),t2.clr();
for(R int i=2;i<=n;i+=2)t1.upd(i,1);
for(R int i=n-(n&1);i>0;i-=2){
f[i]=t1.query(n)-t1.query(id[i])+t2.query(id[i]-1);
t1.upd(id[i],-1),t2.upd(id[i],1);
}
fp(i,1,n)g[i]=(g[i]-f[i])&1;
R int s=0,t=0;
for(R int i=1;i<=n;i+=2)s+=g[i];
for(R int i=2;i<=n;i+=2)t+=f[i];
t>>=1;
if((s&1)!=(t&1))return puts("No"),0;
s=0,t=0;
for(R int i=2;i<=n;i+=2)s+=g[i];
for(R int i=1;i<=n;i+=2)t+=f[i];
t>>=1;
if((s&1)!=(t&1))return puts("No"),0;
return puts("Yes"),0;
}
\(F\)
又做不来系列
先把一个黑点\((x,y)\)转化成\(x\)到\(y\)的一条有向边
又因为两个弱连通块(把有向边视作无向边之后的连通块)之间互不影响,所以我们单独考虑一个弱连通块
首先,如果存在自环,那么这个点所在的整个弱连通块中所有边都会相连(包括自环)
这是因为所有和这个点存在单向边的点都会变成双向边,有双向边后又会形成自环,一直重复之后会把所有边都连起来
判断自环的话,我们把原图进行\(3\)染色,那么会有三种情况
不存在合法染色方案,那么必定有自环,答案就是该弱连通块的\(size\times size\)
存在合法染色方案,但是有一种颜色没有出现,那么无法连上任何一条边
否则的话,若\(color[u]+1\equiv color[v]\pmod{3}\),则\((u,v)\)之间必有一条边,设\(c[i]\)表示颜色为\(i\)的数的出现次数,则答案为\(c[0]\times c[1]+c[1]\times c[2]+c[2]\times c[0]\)
证明的话建议感性理解一下
//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct eg{int v,nx,w;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v,R int w){e[++tot]={v,head[u],w},head[u]=tot;}
int dis[N],c[3],eg,sz,fl,n,m;ll ans;
void dfs(int u,int w){
dis[u]=w,++c[w],++sz;
go(u){
++eg;
if(dis[v]==-1)dfs(v,(dis[u]+e[i].w)%3);
else if(dis[v]!=(dis[u]+e[i].w)%3)fl=0;
}
}
int main(){
scanf("%d%d",&n,&m);
for(R int i=1,u,v;i<=m;++i)scanf("%d%d",&u,&v),add(u,v,1),add(v,u,2);
memset(dis,-1,(n+1)<<2);
fp(i,1,n)if(dis[i]==-1){
eg=sz=c[0]=c[1]=c[2]=0,fl=1;
dfs(i,0);eg>>=1;
if(fl)ans+=(!c[0]||!c[1]||!c[2]?eg:1ll*c[0]*c[1]+1ll*c[1]*c[2]+1ll*c[2]*c[0]);
else ans+=1ll*sz*sz;
}
printf("%lld\n",ans);
return 0;
}
AtCoder Grand Contest 006 题解的更多相关文章
- AtCoder Grand Contest 006
AtCoder Grand Contest 006 吐槽 这套题要改个名字,叫神仙结论题大赛 A - Prefix and Suffix 翻译 给定两个串,求满足前缀是\(S\),后缀是\(T\),并 ...
- AtCoder Grand Contest 006 C:Rabbit Exercise
题目传送门:https://agc006.contest.atcoder.jp/tasks/agc006_c 题目翻译 数轴上有\(N\)只兔子,从\(1\)到\(N\)编号,每只兔子初始位置是\(x ...
- AtCoder Grand Contest 017 题解
A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...
- Atcoder Grand Contest 054 题解
那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...
- AtCoder Grand Contest 030题解
第一次套刷AtCoder 体验良好 传送门 Poisonous Cookies cout<<b+min(c,a+b+); Tree Burning 难度跨度有点大啊 可以证明当第一次转向之 ...
- AtCoder Grand Contest 006 (AGC006) C - Rabbit Exercise 概率期望
原文链接https://www.cnblogs.com/zhouzhendong/p/AGC006C.html 题目传送门 - AGC006C 题意 有 $n$ 个兔子,从 $1$ 到 $n$ 编号, ...
- AtCoder Grand Contest 031题解
题面 传送门 题解 比赛的之后做完\(AB\)就开始发呆了--简直菜的一笔啊-- \(A - Colorful\ Subsequence\) 如果第\(i\)个字母选,那么它前面任意一个别的字母的选择 ...
- AtCoder Grand Contest 039 题解
传送门 \(A\) 首先只有一串的情况下,遇到相同的肯定是改后面那一个最优,然后两串的话可能要分奇偶讨论一下 //quming #include<bits/stdc++.h> #defin ...
- AtCoder Grand Contest 017题解
传送门 \(A\) 直接转移就是了 typedef long long ll; const int N=55; ll f[N][2];int a[N],n,p; int main(){ scanf(& ...
随机推荐
- 雪花算法,生成分布式唯一ID
2.3 基于算法实现 [转载] 这里介绍下Twitter的Snowflake算法——snowflake,它把时间戳,工作机器id,序列号组合在一起,以保证在分布式系统中唯一性和自增性. snowfla ...
- C# vb .net实现羽化效果
在.net中,如何简单快捷地实现Photoshop滤镜组中的羽化效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步 ...
- 12.1 Mapping手动创建
只能在index里的field不存在的时候,才能指定新field的数据类型,field有数据后,就不能再修改field的类型了 可创建的类型如下: integer double date text/s ...
- springboot中常用的依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- C# Microsoft.Office 操作Excel总结
1.导入命名空间: using Microsoft.Office.Interop.Excel; 2.如何打开已有excel文档,或者创建一个新的excel文档 Application app = ...
- CRM, C4C和SAP Hybris的数据库层设计
SAP的product都是DB provider无关的. CRM大家都很熟悉了,application developer最多用Open SQL直接操作表. Netweaver里支持的DB provi ...
- HTTP协议复习二--代理
代理(Proxy)是HTTP协议中请求方和应答方中间的一个环节,作为“中转站”,既可以转发客 户端的请求,也可以转发服务器的应答.代理有很多的种类,常见的有:1.匿名代理:完全“隐匿”了被代理的机器, ...
- Mac 修改hostname
mac终端上输入命令: sudo scutil --set HostName newname # 实例 sudo scutil --set HostName master
- MySQL Index--CREATE INDEX在各版本的优化
FIC(Fast index creation)特性在MySQL 5.5版本中引入FIC(Fast index creation)特性,创建索引时无需再拷贝整表数据,以提升索引的创建速度. FCI 操 ...
- MySQL Replication--开启GTID模式下匿名事务异常
错误环境: OS: CentOS release 6.5 (Final) MySQL: MySQL 5.7.19 主从参数配置: master_info_repository = TABLE rela ...