传送门

\(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题解的更多相关文章

  1. AtCoder Grand Contest 013 C:Ants on a Circle

    题目传送门:https://agc013.contest.atcoder.jp/tasks/agc013_c 题目翻译 给你一个周长为\(L\)的圆,有\(N\)只蚂蚁在圆上爬,速度为一单位距离每秒. ...

  2. AtCoder Grand Contest 017 题解

    A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...

  3. AtCoder Grand Contest 013 E - Placing Squares

    题目传送门:https://agc013.contest.atcoder.jp/tasks/agc013_e 题目大意: 给定一个长度为\(n\)的木板,木板上有\(m\)个标记点,距离木板左端点的距 ...

  4. Atcoder Grand Contest 054 题解

    那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...

  5. AtCoder Grand Contest 030题解

    第一次套刷AtCoder 体验良好 传送门 Poisonous Cookies cout<<b+min(c,a+b+); Tree Burning 难度跨度有点大啊 可以证明当第一次转向之 ...

  6. AtCoder Grand Contest 031题解

    题面 传送门 题解 比赛的之后做完\(AB\)就开始发呆了--简直菜的一笔啊-- \(A - Colorful\ Subsequence\) 如果第\(i\)个字母选,那么它前面任意一个别的字母的选择 ...

  7. AtCoder Grand Contest 039 题解

    传送门 \(A\) 首先只有一串的情况下,遇到相同的肯定是改后面那一个最优,然后两串的话可能要分奇偶讨论一下 //quming #include<bits/stdc++.h> #defin ...

  8. 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(& ...

  9. AtCoder Grand Contest 015题解

    传送门 \(A\) 找到能达到的最大的和最小的,那么中间任意一个都可以被表示出来 typedef long long ll; int n,a,b;ll res; int main(){ scanf(& ...

随机推荐

  1. git重置账号密码

    1.打开控制面板(快捷打开win+R,输入control) 2.点击打开用户账户 3.点击凭据管理器 4.点击windows凭据删除你的git凭据即可

  2. 记录用到的mssql的几个方法

    1.RIGHT ( character_expression , integer_expression ) 返回字符串中从右边开始指定个数的字符 character_expression 字符或二进制 ...

  3. java之struts2之ajax

    1.Ajax 技术在现有开发中使用非常多,大多是做管理类型系统.在servlet中可以使用ajax.在struts2中共还可以使用servlet的方式来实现ajax. 2.案例:用户名检查 publi ...

  4. asp.net core 一个中小型项目实战的起手式——Swagger配置

    交流群:863563315 一.Swagger是什么 Swagger 是一款RESTFUL接口的.基于YAML.JSON语言的文档在线自动生成.代码自动生成的工具. 二.如何在项目中加入Swagger ...

  5. 并发编程之Java锁

    一.重入锁 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized(重量级) 和 ReentrantLock(轻量级)等等 ) .这些已经写好提供的锁为我们开发提 ...

  6. JavaScript 自己写一个 replaceAll() 函数

    JavaScript 的  replace()  方法可以在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. 但是,只输入字符串的话,仅替换第一个字符,当然也可以用正则表达式来进行 ...

  7. Qt 利用飞机图片画五边形

    最近练习Qt,需要一个飞机在屏幕上画五边形.虽然达到的效果不是非常的理想,但是勉强还是达到了效果,欢迎大家指正.用到的飞机图片如下. 第一步:初始化,在构造函数里面,把图片向左旋转18° );ui.l ...

  8. iOS原生与H5交互

    一.WKWebView WKWebView 初始化时,有一个参数叫configuration,它是WKWebViewConfiguration类型的参数,而WKWebViewConfiguration ...

  9. MySQL Index--关联条件列索引缺失导致执行计划性能不佳

    某系统反馈慢SQL影响生产,查看SLOW LOG发现下面慢SQL: SELECT COUNT(DISTINCT m.batch_no) FROM ob_relation r INNER JOIN ob ...

  10. Android笔记(五十一) 短信验证码集成——mob平台

    官方网站:www.mob.com 注册帐号,下载SDK,导入SDK就不说了,主要写一下简单集成如何使用,以后忘记了也可以翻着看看. 详细的可以参考官方文档: http://wiki.mob.com/a ...