传送门

\(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. MVC4 部署 could not load file or assembly system.web.http.webhost 或是其它文件出误

    自从VS2010发布之后使用它来做开发的程序员越来越多,其中很多人使用了MVC来作为新的开发框架,但是在系统部署的时候我们也遇到诸多问题,因为目前大多数windows服务器采用的还是Windows S ...

  2. screen命令下,自启动设置

    建立autostart.sh文件 #!/bin/bash screen_name=$"coffeetest:9100" screen -dmS $screen_name cmd=$ ...

  3. OO——JML作业总结

    目录 第三单元博客作业 JML语言理论基础 1.注释结构 2.JML表达式 3.方法规格 4.类型规格 应用工具链 JMLUnitNG使用实例 作业架构设计 第一次作业 第二次作业 第三次作业 BUG ...

  4. FreeRTOS中断测试

    configMAX_SYSCALL_INTERRUPT_PRIORITY 高于此优先级的中断,不能被禁止 #ifdef __NVIC_PRIO_BITS #define configPRIO_BITS ...

  5. iOS 静态、全局变量、常量

    关键字static 两个概念:生命周期.作用域生命周期:这个变量能存活多久,它所占用的内存什么时候分配,什么时候收回.作用域:这个变量在什么区域是可见的,可以拿来用的. static分两种情况:修饰局 ...

  6. 如何在backoffice里创建Hybris image container以及分配给product

    登录backoffice,在media container视图点击新建按钮: Catalog选择Product Catalog: 在Properties界面,可以选择media实例放入该contain ...

  7. 根据值获取枚举类对象工具类EnumUtils

    枚举类 public enum Sex { man("M","男"),woman("W","女"); private S ...

  8. SQL月度统计

    select Convert ( VARCHAR(7),CreateTime,120) as Date ,sum(Money) as M FROM [LBAmmeterDB].[dbo].Am_Tas ...

  9. 02- web-mini框架添加路由、MySQL(二)

    本篇在上篇的基础上为其增设路由功能,同时将上篇中的数据库中数据备份添加进去. 一.装饰器 在之前有介绍过为一个函数不改变源代码不改变原函数的调用方式下为其增设附加功能,需要用到装饰器,而在该上篇的we ...

  10. sql的匹配和正则表达式

    1. 匹配:like 关键字 #假设存在表 my_test_copy select * from my_test_copy; 则使用like关键词匹配:注意下划线 '_'和百分号 '%' # 下划线' ...