AtCoder Grand Contest 013题解
\(A\)
先把相同的缩一起,然后贪心就可以了
//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=2e5+5;
int a[N],tot,n,res;
int main(){
scanf("%d",&n);
fp(i,1,n)scanf("%d",&a[i]);
fp(i,1,n)if(a[i]!=a[i-1])a[++tot]=a[i];
n=tot,res=1;
for(R int l=1,r=2;r<=n;l=r++){
if(a[l]<a[r])while(r<=n&&a[r]>a[r-1])++r;
else while(r<=n&&a[r]<a[r-1])++r;
if(r<=n)++res;
}
printf("%d\n",res);
return 0;
}
\(B\)
随便找一个点开始\(dfs\)出一条链一直到不能\(dfs\)为止,那么发现这条链的末尾必定满足所有与它相连的点都在路径中。那么找出两条这样的链拼起来就可以了
//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=2e5+5;
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int st[N],vis[N],top,n,m;
void dfs(int u){vis[u]=1;go(u)if(!vis[v]){st[++top]=v,dfs(v);break;}}
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),add(v,u);
st[++top]=1,dfs(1),reverse(st+1,st+1+top),dfs(1);
printf("%d\n",top);
fp(i,1,top)printf("%d ",st[i]);
return 0;
}
\(C\)
首先如果我们认为碰撞之后继续走,那么所有的最终位置都可以算出来。而因为按原来的走法相对顺序是不变的,所以我们只要推出\(1\)号点的位置就可以依次推出其他点的位置
一开始时一号蚂蚁坐标最小,每当有蚂蚁从\(L-1\)爬到\(0\),一号蚂蚁的排名就\(+1\),反之如果有蚂蚁从\(0\)爬到\(L-1\),一号蚂蚁排名就\(-11\),对于每个点都计算一下就可以算出一号蚂蚁最终的排名了
//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=2e5+5;
int a[N],pos[N],n,L,T,x,w;ll t;
int main(){
scanf("%d%d%d",&n,&L,&T);
fp(i,0,n-1){
scanf("%d%d",&x,&w),w=(w==2?-1:1);
pos[i]=((x+T*w)%L+L)%L;
if(w==1)t+=(x+T)/L;else t-=(L-1-x+T)/L;
}
t=(t%n+n)%n;
sort(pos,pos+n);
fp(i,t,n-1)printf("%d\n",pos[i]);
fp(i,0,t-1)printf("%d\n",pos[i]);
return 0;
}
\(D\)
首先第\(1\)个球和第\(2m\)个球显然颜色任选,那么我们去掉这两个,变成了\(m-1\)次放两个球选两个球的操作,同时初始时有\(n-1\)个球
用\(1\)表示黑球,\(0\)表示白球,那么每次放球有三种选择,\(11,00,01\)(\(01\)和\(10\)默认为同一种,到时候方案数\(\times 2\)就行了)。对于原来的袋中,球的总数不变,如果只考虑黑球的个数,那么三种选择分别相当于\(+1,-1,0\)。我们用\(f[i][j]\)表示考虑了前\(i\)个位置且黑球有\(j\)个,只要合法就转移就是了
然而有一个问题就是如果序列合法时袋子里剩下球不同会被当做不一样的方案,导致重复计算,一个方法是我们减去袋中原有小于等于\(n-2\)个球时的答案,这是因为对于每一种合法的序列必然存在一个初始的袋中的球的集合卡到上界的方案(要么是白球数量卡到上界,要么是黑球数量卡到上界),那么在\(n-2\)的情况中所有这些方案都不会被计算,所以减去就能得到正确的方案了
//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 P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
const int N=3005;
int f[N][N][2],n,m,res;
int main(){
scanf("%d%d",&n,&m),--n,--m;
f[0][0][1]=1;
fp(i,1,n)f[0][i][0]=1;
fp(i,0,m-1)fp(j,0,n)fp(k,0,1)if(f[i][j][k]){
if(j)upd(f[i+1][j-1][k|(j==1)],f[i][j][k]);
if(j<n)upd(f[i+1][j+1][k],f[i][j][k]);
upd(f[i+1][j][k],add(f[i][j][k],f[i][j][k]));
}
fp(i,0,n)upd(res,f[m][i][1]);
printf("%d\n",mul(res,4));
return 0;
}
\(E\)
首先,写出暴力是很容易的,而且优化到\(O(n)\)也是很容易的,不过如果有能继续优化到能过的话请在下面提醒一下我怎么做
这里有一个套路,就是把平方和转化成有序对,即我们可以把原问题转化成初始时有\(n\)个格子,\(1\)格子左边和\(n\)格子右边强制有隔板,中间隔板随便插,每个格子上可以随便放\(0/1\)两种颜色的球,要求每两个隔板之间两种颜色的球出现且仅出现一次,求方案数
这个的话,我们设\(f[i][j]\)表示考虑到第\(i\)个格子是否放球以及第\(i-1\)和\(i\)之间是否放隔板,且上一个隔板到\(i\)之间共有\(j\)个球,最后的答案就是\(f[n][2]\)。我们发现对于所有\(i-1\)和\(i\)之间能放隔板的格子,转移是一样的,而所有不能放的也是一样的,所以我们可以用一个\(3\times 3\)的矩阵来表示这一个转移,最后矩乘优化即可
先给出暴力的代码(这是\(yyb\)聚聚的)
f[0][0]=1;
for(int i=1,pos=1;i<=n;++i)
{
if(i!=a[pos])
for(int j=0;j<3;++j)
add(f[i][j],((j==1)?2:1)*f[i-1][2]%MOD);
for(int j=0;j<3;++j)
{
add(f[i][j],f[i-1][j]);
if(j<2)add(f[i][j+1],(2-j)*f[i-1][j]%MOD);
if(j<1)add(f[i][j+2],f[i-1][j]);
}
if(i==a[pos])++pos;
}
printf("%d\n",f[n][2]);
然后是这题的代码
//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 P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
const int N=2e5+5;
struct Matrix{
int a[3][3];
inline Matrix(){memset(a,0,sizeof(a));}
inline int* operator [](const int &x){return a[x];}
inline Matrix operator *(Matrix b){
Matrix c;
fp(i,0,2)fp(k,0,2)fp(j,0,2)upd(c[i][j],mul(a[i][k],b[k][j]));
return c;
}
}bin[35],A,B,ans;
int a[N],n,m;
inline Matrix ksm(R int x){
Matrix c;c[0][0]=c[1][1]=c[2][2]=1;
for(R int i=0;x;x>>=1,++i)if(x&1)c=c*bin[i];
return c;
}
int main(){
scanf("%d%d",&n,&m);
fp(i,1,m)scanf("%d",&a[i]),++a[i];
A[0][0]=1,A[0][1]=2,A[0][2]=1;
A[1][0]=0,A[1][1]=1,A[1][2]=1;
A[2][0]=1,A[2][1]=2,A[2][2]=2;
B=A,B[2][0]=0,B[2][1]=0,B[2][2]=1;
bin[0]=A;fp(i,1,30)bin[i]=bin[i-1]*bin[i-1];
ans[0][0]=ans[1][1]=ans[2][2]=1;
fp(i,1,m)ans=ans*ksm(a[i]-a[i-1]-1)*B;
ans=ans*ksm(n-a[m]);
printf("%d\n",ans[0][2]);
return 0;
}
\(F\)
首先我们把\(C\)给\(sort\)之后重新标号为\(1,2,...,n+1\),然后对于每个\(a\)用最小的\(i\)满足\(a\leq c_i\)的\(i\)来表示,对\(b\)也同样这样离散
先假设所有牌都翻到正面是否可行,我们初始时令一个\([1,n+1]\)的数列全部为\(0\),且令每一个\([i,n+1]-1\),每一个\([a_i,n+1]+1\),如果最终数列中所有数都大于等于\(0\)证明可行。而对于询问,我们可以分别考虑是选择\(d\)还是\(e\),取较优的那个即可
对于询问,假设当前选择了\(x\),那么序列要满足\([x,n+1]\)全都大于等于\(-1\)且前面都大于等于\(0\)
对于一对\(a,b\),如果\(b<a\),那么我们可以通过翻转使得\([b,a-1]+1\),然后减掉一个正面的个数。如果把所有的区间取出来,我们从后往前做,对于每一个小于\(-1\)的位置,找到覆盖它的且左端点最左的一个区间,容易证明最优方案里这个区间一定会被选择翻转,那么我们把它翻转,然后正面朝上个数\(-1\),并删掉这个区间就是了
然后再从右往左做一遍,每次对于小于\(0\)的位置找到覆盖它且右端点最右的区间,同样选择翻转这个区间就是了。此时\([1,i]\)中所有元素都大于等于\(0\),\([i+1,n+1]\)都大于等于\(-1\),那么\(x=i+1\)的答案就出来了
//quming
#include<bits/stdc++.h>
#define R register
#define fi first
#define se second
#define pb emplace_back
#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 pair<int,int> pi;
const int N=2e5+5,inf=0x3f3f3f3f;
int a[N],b[N],c[N],d[N],f[N];
int n,Q,tot;
priority_queue<pi,vector<pi>,greater<pi> >h;
priority_queue<pi>q;
vector<int>li[N],ri[N];
inline void chg(R int x,R int y){for(;x<=n+1;x+=x&-x)d[x]+=y;}
inline int query(R int x){R int res=0;for(;x;x-=x&-x)res+=d[x];return res;}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n);
fp(i,1,n)scanf("%d%d",&a[i],&b[i]);
fp(i,1,n+1)scanf("%d",&c[i]);
sort(c+1,c+n+1+1);
fp(i,1,n){
a[i]=lower_bound(c+1,c+n+1+1,a[i])-c;
b[i]=lower_bound(c+1,c+n+1+1,b[i])-c;
}
fp(i,1,n+1)chg(i,-1);fp(i,1,n)chg(a[i],1);
fp(i,1,n)if(b[i]<a[i])ri[a[i]-1].pb(b[i]);
fd(i,n+1,0){
for(auto v:ri[i])h.push(pi(v,i));
while(query(i)<-1){
if(h.empty()||h.top().fi>i){tot=inf;break;}
chg(h.top().fi,1),chg(h.top().se+1,-1),h.pop(),++tot;
}
if(tot>=inf){
scanf("%d",&Q);
fp(i,1,Q)puts("-1");
return 0;
}
}
while(!h.empty())li[h.top().fi].pb(h.top().se),h.pop();
fp(i,0,n+1){
for(auto v:li[i])q.push(pi(v,i));
while(query(i)<0){
if(q.empty()||q.top().fi<i){tot=inf;break;}
chg(q.top().se,1),chg(q.top().fi+1,-1),q.pop(),++tot;
}
f[i]=tot;
if(tot>=inf){
fp(k,i,n+1)f[k]=inf;
break;
}
}
scanf("%d",&Q);
for(R int d,e,res;Q;--Q){
scanf("%d%d",&d,&e);
d=lower_bound(c+1,c+n+1+1,d)-c;
e=lower_bound(c+1,c+n+1+1,e)-c;
res=-1,cmax(res,n+1-f[d-1]),cmax(res,n-f[e-1]);
printf("%d\n",res);
}
return 0;
}
AtCoder Grand Contest 013题解的更多相关文章
- AtCoder Grand Contest 013 C:Ants on a Circle
题目传送门:https://agc013.contest.atcoder.jp/tasks/agc013_c 题目翻译 给你一个周长为\(L\)的圆,有\(N\)只蚂蚁在圆上爬,速度为一单位距离每秒. ...
- AtCoder Grand Contest 017 题解
A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...
- AtCoder Grand Contest 013 E - Placing Squares
题目传送门:https://agc013.contest.atcoder.jp/tasks/agc013_e 题目大意: 给定一个长度为\(n\)的木板,木板上有\(m\)个标记点,距离木板左端点的距 ...
- 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 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(& ...
- AtCoder Grand Contest 015题解
传送门 \(A\) 找到能达到的最大的和最小的,那么中间任意一个都可以被表示出来 typedef long long ll; int n,a,b;ll res; int main(){ scanf(& ...
随机推荐
- golang --iota 用法
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" ...
- Java 枚举和抽象类添加状态值
枚举: public enum CourseTypeEnum { VIDEO_COURSE(1,"录制课程"), LIVE_COURSE(2,"直播课程"), ...
- AspNetCore网关集成Swagger访问使用IdentityServer保护的webapi项目
创建webapi项目 创建四个webapi项目,两个处理业务,一个网关,一个验证中心.四个项目对应的端口如下, ApiGateway:1999 IdentityServer:16690 Service ...
- 使用springboot实现一个简单的restful crud——02、dao层单元测试,测试从数据库取数据
接着上一篇,上一篇我们创建了项目.创建了实体类,以及创建了数据库数据.这一篇就写一下Dao层,以及对Dao层进行单元测试,看下能否成功操作数据库数据. Dao EmpDao package com.j ...
- 【转载】Javascript使用Math.random()随机数函数生成1至1000的随机数
在Javascript代码编写过程中,有时候我们需要使用Js来生成随机数,清除ajax的get请求缓存的时候我们会带上一个随机数来解决此问题,此外在其他应用中也可能使用到随机数,在Javascript ...
- Core Animation笔记(特殊图层)
1.shapeLayer: 渲染快速,内存占用小,不会被图层边界裁掉(可以在边界之外绘制),不会像素化(当做3D变化如缩放是不会失真) CGRect rect = self.containerView ...
- react-router-dom下的BrowserRouter和HashRouter
奇思妙想的
- gitlab自带的Nginx与原Nginx冲突的解决方案
gitlab 推荐方案2 默认情况下,gitlab使用自带的Nginx,占用80端口,这样就与系统原本安装的Nginx冲突.导致其中一个nginx无法启动 我的gitlab可以正常启动,当再部署一个接 ...
- PXE+Kickstart无人值守安装---CentOS7.
1.安装一台CentOS7.x桌面版本系统的服务器,关闭selinux和防火墙: 2.在服务器安装pxe+kickstart无人值守需要的软件 : yum install dhcp tftp-serv ...
- HTML&CSS基础-样式的继承
HTML&CSS基础-样式的继承 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HTML源代码 <!DOCTYPE html> <html> & ...