传送门

\(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=15;
char mp[N][N];int vis[N][N],n,m;
bool dfs(int x,int y){vis[x][y]=1;if(x==n&&y==m)return true;R int c=0;if(x<n&&mp[x+1][y]=='#')++c;if(y<m&&mp[x][y+1]=='#')++c;if(c!=1)return false;if(x<n&&mp[x+1][y]=='#')return dfs(x+1,y);if(y<m&&mp[x][y+1]=='#')return dfs(x,y+1);
}
int main(){scanf("%d%d",&n,&m);fp(i,1,n)scanf("%s",mp[i]+1);if(mp[1][1]!='#'||mp[n][m]!='#')return puts("Impossible"),0;if(!dfs(1,1))return puts("Impossible"),0;fp(i,1,n)fp(j,1,m)if((mp[i][j]=='#')!=vis[i][j])return puts("Impossible"),0;return puts("Possible"),0;
}

\(B\)

先把\(a\)和\(b\)分别设成\(1\)到\(n\)来满足第一第二个条件

我们发现,如果把\(a_i\)到\(a_n\)全部加上\(x\),且\(b_1\)到\(b_i\)全部加上\(x\),可以使\(a_i+b_i\)相对增加\(x\)且仍满足第一第二个条件

那么我们令\(p_i\)相对增加\(i\)即可满足第三个条件,最大的数是\(O(n^2)\)级别的,不会超过\(10^9\)

const int N=1e5+5;
int a[N],b[N],p[N],n;
int main(){scanf("%d",&n);fp(i,1,n)scanf("%d",&p[i]),a[p[i]]+=i,b[p[i]]+=i;fp(i,1,n)a[i]+=a[i-1];fd(i,n,1)b[i]+=b[i+1];fp(i,1,n)printf("%d%c",a[i]+i," \n"[i==n]);fp(i,1,n)printf("%d%c",b[i]+n-i+1," \n"[i==n]);return 0;
}

\(C\)

完全想不到啊……

首先我们转化为有\(2n+1\)个物品,每次随机删去相邻的两个,求距离的期望和

我们发现一开始时距离是一个等差数列,并且如果维护每两个点间距离的期望,那么一次操作之后仍然是等差数列

具体的证明的话,如果删去的两个点在边界上显然操作之后还是等差,否则如果对于一个长度为\(d+kx\)的段,删去这段的两个顶点之后这一段长度变为\(3d+3kx\),所以令\(d_i\)表示第\(i\)个点和第\(i+1\)个点的期望距离,\(d_i'\)为操作之后的期望距离,那么总共有\(2n\)种删法,所以\(d_i'={i\over 2n}(d_i+2x)+{1\over 2n}(3d_i+3x)+{2n-i-1\over 2n}d_i={2n+2\over 2n}d_i+{2i+3\over 2n}x\),所以\(x'=d_i'-d_{i-1}'={2n+4\over 2x}x={n+2\over n}x\),是一个定值

然后再来考虑新的等差数列的首项,如果删了\(1,2\),首项变为\(d+2x\),如果删了\(2,3\),首项变为\(3x+3d\),否则不变,所以新的首项\(d_1^{'}=\frac{1}{2n}*(d_1+2x)+\frac{1}{2n}*(3d_1+3x)+\frac{2n-2}{2n}*d_1=\frac{(2n+2)d_1+5x}{2n}\)

然后每次计算即可

int n;double d,x,res;
int main(){scanf("%d%lf%lf",&n,&d,&x);for(;n;--n){res+=(d+((n<<1)-1)*x*0.5),d=(((n<<1)+2)*d+5*x)/(n<<1),x=(n+2)*x/n;}printf("%.12lf\n",res);return 0;
}

\(D\)

首先我们容易写出一个暴力,设\(f_i\)表示把前\(i\)个数全部处理完的最小时间,则\(f_i=\min_{j<i}(f_j+\max(t,(a_i-a_{j+1})))\)

因为\(\max(t,(a_i-a_{j+1})\)的分界点是随\(i\)递增而不降的,所以我们可以直接把分界点两边的答案分别用\(set\)记录下来然后直接查询就好了

//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=5e5+5;const ll inf=1e18;
int n,t,e,a[N];ll f[N];
inline ll min(R ll x,R ll y){return x<y?x:y;}
inline ll max(R ll x,R ll y){return x>y?x:y;}
struct Queue{priority_queue<ll,vector<ll>,greater<ll> >A,B;inline void push(R ll x){A.push(x);}inline void pop(R ll x){B.push(x);}inline ll top(){while(!B.empty()&&A.top()==B.top())A.pop(),B.pop();return A.empty()?inf:A.top();}
}s1,s2;
int main(){scanf("%d%d%d",&n,&e,&t);fp(i,1,n)scanf("%d",&a[i]);s2.push(0);for(R int i=1,j=0;i<=n;++i){while(j<i&&((a[i]-a[j+1])<<1)>=t)s1.push(f[j]-(a[j+1]<<1)),s2.pop(f[j]),++j;f[i]=inf,cmin(f[i],s1.top()+(a[i]<<1)),cmin(f[i],s2.top()+t);s2.push(f[i]);}printf("%lld\n",f[n]+e);return 0;
}

\(E\)

首先肯定要二分答案,且因为每条边只能经过两次,所以进入一颗子树之后必须遍历完其中所有节点才能出来

对于每一个点,记录一个状态\((a,b)\)表示一条合法的路径是花费\(a\)的代价从当前节点走到某个叶子,花费\(b\)的代价从某个叶子走回到当前节点,那么对于左子树的\((a,b)\)和右子树的\((c,d)\),只有当\(b+w_i+c+w_j\leq mid\)的时候它们才能合并成\((a+w_i,d+w_j)\),同理也要判断一下是否能反过来合并成\((c+w_j,b+w_i)\)

每一次把左右儿子的状态进行合并,最后只要\(1\)号点存在合法的状态就说明\(mid\)可行

有一个优化,就是对于一个合法的\(a\)来说,它对应的\(b\)一定是越小越好,那么我们可以对于左子树按第一维排序,右子树按第二位排序,这样合并的复杂度就可以优化到\(O(n)\)了

然而状态数可能会比较多,所以我们每一次用状态数小的去合并状态数大的,这样状态数\(S_u\leq 2\min(S_i,S_j)\),总的状态数是\(O(n\log n)\)的,于是总复杂度为\(O(n\log^2 n)\)

然而比较奇怪的是我如果用状态数大的去合并小的不是\(T\)而是\(WA\)……好迷啊……

//quming
#include<bits/stdc++.h>
#define R register
#define pb push_back
#define fi first
#define se second
#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;
typedef vector<pi> vc;
const int N=5e5+5;
int ls[N],rs[N],w[N],mn[N],n,l,r,mid,ans;vc f[N];
inline int min(R int x,R int y){return x<y?x:y;}
inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;}
inline bool cmpx(const pi &x,const pi &y){return x.fi<y.fi;}
inline bool cmpy(const pi &x,const pi &y){return x.se<y.se;}
void merge(vc &a,vc &ls,vc &rs){R int n=ls.size(),m=rs.size();if(!n||!m)return;if(n>m)ls.swap(rs),swap(n,m);sort(ls.begin(),ls.end(),cmpy);sort(rs.begin(),rs.end(),cmpx);mn[0]=rs[0].se;fp(i,1,m-1)mn[i]=min(mn[i-1],rs[i].se);for(R int i=0,j=m-1;i<n;++i){while(j>=0&&ls[i].se+rs[j].fi>mid)--j;if(j<0)break;a.pb(pi(ls[i].fi,mn[j]));}sort(ls.begin(),ls.end(),cmpx);sort(rs.begin(),rs.end(),cmpy);mn[0]=rs[0].fi;fp(i,1,m-1)mn[i]=min(mn[i-1],rs[i].fi);for(R int i=0,j=m-1;i<n;++i){while(j>=0&&ls[i].fi+rs[j].se>mid)--j;if(j<0)break;a.pb(pi(mn[j],ls[i].se));}
}
void dfs(int u){f[u].clear();if(!ls[u])return f[u].pb(pi(w[u],w[u])),void();dfs(ls[u]),dfs(rs[u]);merge(f[u],f[ls[u]],f[rs[u]]);for(auto &v:f[u])v.fi+=w[u],v.se+=w[u];
}
int main(){scanf("%d",&n);for(R int i=2,fa,x;i<=n;++i){scanf("%d%d",&fa,&x);(ls[fa]?rs[fa]:ls[fa])=i,w[i]=x;}l=0,r=1e9,ans=1e9;while(l<=r){mid=(l+r)>>1,dfs(1);f[1].empty()?l=mid+1:(ans=mid,r=mid-1);}printf("%d\n",ans);return 0;
}

\(F\)

好迷……

首先我们发现,一个字母往下的轨迹视为一条路径,那么这条路径会是一条折线,且这个折线越早拐弯越好

那么我们对于\(t\)从后往前贪心的匹配,找到\(s\)中最后面的能匹配的位置,然后判断是否会和之前的折线有交点

感觉我还是说不太清楚……建议看一下官方题解的图

//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=1e6+5;
char a[N],b[N];int q[N],h,t,n,res;
int main(){scanf("%d%s%s",&n,a+1,b+1);if(!strcmp(a+1,b+1))return puts("0"),0;h=1,t=0;for(R int i=n,p=n;i;--i)if(b[i]!=b[i-1]){cmin(p,i);while(p&&a[p]!=b[i])--p;if(!p)return puts("-1"),0;while(h<=t&&q[h]-(t-h+1)>=i)++h;q[++t]=p;if(i!=p)cmax(res,t-h+1);}printf("%d\n",res+1);return 0;
}

转载于:https://www.cnblogs.com/yuanquming/p/11438531.html

AtCoder Grand Contest 007题解相关推荐

  1. [atcoder]AtCoder Grand Contest 027题解

    [题目链接] https://agc027.contest.atcoder.jp/ A [题解] 题意: 是把xxx个糖果分给nnn个人,一个人如果恰好分到aia_{i}ai​个糖果就会高兴.求最多使 ...

  2. AtCoder Grand Contest 028题解

    C - Min Cost Cycle 思路好6啊,考试想了半天都没有想出来. 一直在想一个错误的贪心算法. 首先,我们把加一条权值为$min(Ax,By)$的边变成两条权值分别为$Ax,By$的边. ...

  3. AtCoder Grand Contest 013 题解

    A - Sorted Arrays 贪心,看看不下降和不上升最长能到哪,直接转移过去即可. 1 //waz 2 #include <bits/stdc++.h> 3 4 using nam ...

  4. Atcoder Grand Contest 005 题解

    A - STring 用一个栈模拟即可. //waz #include <bits/stdc++.h>using namespace std;#define mp make_pair #d ...

  5. 【每日亿题#12】AtCoder Grand Contest 021 (A ~ F)全部题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 文章目录 AtCoder Grand Contest 021 题解 A. Digit Sum 2 B. ...

  6. AtCoder题解——AtCoder Grand Contest 048——A - atcoder < S

    题目相关 题目链接 AtCoder Grand Contest 048 A 题,https://atcoder.jp/contests/agc048/tasks/agc048_a. Problem S ...

  7. AtCoder题解 —— AtCoder Grand Contest 050 —— B - Three Coins —— 动态规划

    题目相关 题目链接 AtCoder Grand Contest 050 B 题,https://atcoder.jp/contests/agc050/tasks/agc050_b. Problem S ...

  8. AtCoder Grand Contest 008: Contiguous Repainting(思维)

    Contiguous Repainting 时间限制: 2 Sec  内存限制: 256 MB 提交: 69  解决: 22 [提交][状态][讨论版][命题人:admin] 题目描述 There a ...

  9. AtCoder Grand Contest 017

    AtCoder Grand Contest 017 A - Biscuits 有\(n\)个数,问有多少个集合的数的和模\(2\)余\(P\). 随便\(dp\)一下就好了. #include< ...

  10. AtCoder Beginner Contest 197 题解(A ~ F)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A - Rotate B - Visibility C - ORXOR D - Opposite ...

最新文章

  1. HDOJ 1036 输入输出 水
  2. 面向对象——多态,抽象类,接口(二)
  3. 揭秘:如何为 Kubernetes 实现原地升级
  4. cheat sheet for cs221 at stanford: good luck
  5. python函数使用易错举例
  6. Unity3d-跨平台(二)
  7. Java枚举getDeclaringClass()方法与示例
  8. mysql 查询某个字段SQL语句【mysql语句】
  9. android 事件参数传递,android-databinding – 使用android DataBinding库如何将参数传递给绑定事件...
  10. 深入分析同步工具类之AbstractQueuedSynchronizer
  11. iconfont 图标宽高出问题_IconFont使用注意点
  12. aspectjweaver AspectJ
  13. 【第一讲】APK应用程序的解包、修改、编辑、打包及应用(转)
  14. D. Aerodynamic(思维+计算几何判中心对称图形)
  15. 耗时两天,Html实现小米官网
  16. Reverb详细大解说
  17. 货币银行学简答论述题
  18. 中职升高职c语言程序设计教程课后答案,2020年高职单招计算机类技能复习题及答案(中职生)...
  19. 用python 编写一个简单的游戏
  20. 企业微信号发消息给指定成员

热门文章

  1. sai笔记6-sai2版本新增的功能
  2. linux中分号转义字符,Linux职场技术篇-Linux shell中元字符、转义符、通配符的使用方法...
  3. 英语标点中有没有分号?
  4. PR菜鸟教程:如何剪切掉其中不需要的片段
  5. 整除光棍 — C语言【模拟手算除法(附过程图解)】
  6. 模板--Guass消元法(求解多元一次方程组)
  7. 分布临界值表python
  8. PAT乙级1055 集体照
  9. apache 开启 网页压缩
  10. 美图秀秀怎么无缝拼图