[Atcoder Regular Contest 065] Tutorial
Link:
C:
最好采取逆序贪心,否则要多考虑好几种情况
(从前往后贪心的话不能无脑选“dreamer”,"er"可能为"erase"/"eraser"的前缀)
#include <bits/stdc++.h> using namespace std;
string s;
int main()
{
cin>>s;
for(int cur=s.size();cur;)
if(cur>=&&s.substr(cur-,)=="erase") cur-=;
else if(cur>=&&s.substr(cur-,)=="dream") cur-=;
else if(cur>=&&s.substr(cur-,)=="eraser") cur-=;
else if(cur>=&&s.substr(cur-,)=="dreamer") cur-=;
else return puts("NO"),;
puts("YES");
return ;
}
Problem C
注意:$strncpy$和$s.substr()$的第三个参数为长度
D:
题意:求与点$i$在图$G1$和图$G2$中的连通块序号均相同的点的个数
设1个点的序号对为$(a,b)$,其实就是求每对$(a,b)$的个数
然而我一开始沙茶得以为只能$O(n^2)$来统计……
明显用上$set$就只要$O(m*log(n))$了嘛,多维的统计都可以用$set$优化!
先跑两遍$dfs$求出每个点的$(a,b)$,再利用$set$优化$pair$的统计就好了
#include <bits/stdc++.h> using namespace std;
typedef pair<int,int> P;
const int MAXN=2e5+;
map<P,int> mp;
struct edge{int nxt,to;}e[MAXN<<];
int c1[MAXN],c2[MAXN],sum1[MAXN],sum2[MAXN];
int n,k,l,x,y,head[MAXN],vis[MAXN],res[MAXN],tot,cnt; void add_edge(int from,int to)
{
e[++tot].nxt=head[from];e[tot].to=to;head[from]=tot;
e[++tot].nxt=head[to];e[tot].to=from;head[to]=tot;
} void dfs(int x,int c,int* col)
{
vis[x]=true;col[x]=c;
for(int i=head[x];i;i=e[i].nxt)
if(!vis[e[i].to]) dfs(e[i].to,c,col);
} void solve(int esum,int* col)
{
tot=cnt=;
memset(head,,sizeof(head));
memset(vis,false,sizeof(vis));
for(int i=;i<=esum;i++)
scanf("%d%d",&x,&y),add_edge(x,y);
for(int i=;i<=n;i++)
if(!vis[i]) dfs(i,++cnt,col);
} int main()
{
scanf("%d%d%d",&n,&k,&l);
memset(res,0x3f,sizeof(res));
solve(k,c1);solve(l,c2);
for(int i=;i<=n;i++)
sum1[c1[i]]++,sum2[c2[i]]++;
for(int i=;i<=n;i++)
mp[P(c1[i],c2[i])]++;
for(int i=;i<=n;i++)
printf("%d ",mp[P(c1[i],c2[i])]); return ;
}
Problem D
如果只求连通块最好使用并查集
提升效率并能减少代码量
E:
好像题目中专门提到曼哈顿/切比雪夫距离的任意一个往令一个想就对了……
设$a,b$两点间的初始距离为$d$,那么将所有距离为$d$的两点都连边,找到$a$所在的连通块即可
但曼哈顿距离涉及到了两个量,很难进行统一处理,因此要转换成切比雪夫距离
于是问题转化为将$max(|X_i-X_j|,|Y_i-Y_j|)=d$的$i,j$连边
明显可以排序后采取二分的方式,对于每个$X_i$,找到$X_j=X_i+d$中符合$Y_i-d\le Y_j\le Y_i+d$的点的个数,记为$cnt[i]$
接下来将$X_i$与$Y_i$交换后进行相同的操作,只不过要排除$|X_i-X_j|=|Y_i-Y_j|=d$的情况
最后$dfs$求出$a$所在连通块中$cnt$的总和$res=\sum cnt[i]$
要注意连边的细节:不能暴力连边,那样复杂度变为了$O(n^2)$
可以发现每次是向一个区间连边,且只要保证连通性不变,因此只要将区间连成一条链就行了!复杂度为$O(n)$
#include <bits/stdc++.h> using namespace std;
typedef long long ll;
const int MAXN=1e5+;
struct edge{int nxt,to;}e[MAXN*];//一定要开8倍空间
struct data{int x,y,id;}dat[MAXN];
int n,d,a,b,x,y,head[MAXN],vis[MAXN],cnt[MAXN],tot=;
ll res=; void add_edge(int from,int to)
{
e[++tot].nxt=head[from];e[tot].to=to;head[from]=tot;
e[++tot].nxt=head[to];e[tot].to=from;head[to]=tot;
} bool operator < (data a,data b)
{
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
} void solve(int k)
{
sort(dat+,dat+n+);
int cur,lst,l,r;
for(cur=lst=l=r=;cur<=n;cur++)
{
while((dat[l].x<dat[cur].x+d||dat[l].x==dat[cur].x+d&&dat[l].y<dat[cur].y-k)&&l<=n) l++;
while((dat[r].x<dat[cur].x+d||dat[r].x==dat[cur].x+d&&dat[r].y<=dat[cur].y+k)&&r<=n) r++;
if(l>n) break;
cnt[dat[cur].id]+=r-l;lst=max(lst,l);
if(lst>=r) continue; add_edge(dat[cur].id,dat[lst].id);
for(;lst<r-;lst++) add_edge(dat[lst].id,dat[lst+].id);
}
} void dfs(int x)
{
vis[x]=true;res+=cnt[x];
for(int i=head[x];i;i=e[i].nxt)
if(!vis[e[i].to]) dfs(e[i].to);
} int main()
{
scanf("%d%d%d",&n,&a,&b);
for(int i=;i<=n;i++)
scanf("%d%d",&x,&y),dat[i]={x+y,x-y,i}; d=max(abs(dat[a].x-dat[b].x),abs(dat[a].y-dat[b].y));
solve(d);
for(int i=;i<=n;i++) swap(dat[i].x,dat[i].y);
solve(d-); dfs(a);printf("%lld",res);
return ;
}
Problem E
Tip:此题边集数组要开8倍空间,但我觉得4倍就够了?跪求神犇们指点啊……
F:
对于每个点而言,其实只要关心其能翻转到的最右位置就好了,中间重复的翻转可以不管
于是可以先求出$lst[i]$表示第$i$位能翻转到的最右位置
令$dp[i][j]$为已经确定前$i-1$位,还有$j$个1可以自由支配时的方案数
常规地分第$i$位选$0/1$递推即可,$dp[n+1][0]$即为答案
#include <bits/stdc++.h> using namespace std;
const int MAXN=,MOD=1e9+;
char s[MAXN];
int n,m,x,y,pre[MAXN],lst[MAXN],dp[MAXN][MAXN]; int main()
{
scanf("%d%d%s",&n,&m,s+);s[n+]='';
for(int i=;i<=n+;i++) //对第n+1项也要更新
pre[i]=(s[i]-'')+pre[i-],lst[i]=i;
for(int i=;i<=m;i++)
scanf("%d%d",&x,&y),lst[x]=max(lst[x],y);
for(int i=;i<=n+;i++) lst[i]=max(lst[i],lst[i-]); dp[][pre[lst[]]]=;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(dp[i][j])
{
int l=lst[i]+,r=lst[i+];
if(j) (dp[i+][pre[r]-pre[l-]+j-]+=dp[i][j])%=MOD;
if(lst[i]-(i-)-j) (dp[i+][pre[r]-pre[l-]+j]+=dp[i][j])%=MOD;
}
printf("%d",dp[n+][]);
return ;
}
Problem F
[Atcoder Regular Contest 065] Tutorial的更多相关文章
- [Atcoder Regular Contest 060] Tutorial
Link: ARC060 传送门 C: 由于难以维护和更新平均数的值: $Average->Sum/Num$ 这样我们只要用$dp[i][j][sum]$维护前$i$个数中取$j$个,且和为$s ...
- [Atcoder Regular Contest 061] Tutorial
Link: ARC061 传送门 C: 暴力$dfs$就好了 #include <bits/stdc++.h> using namespace std; typedef long long ...
- [Atcoder Regular Contest 064] Tutorial
Link: ARC064 传送门 C: 贪心+对边界的特殊处理 #include <bits/stdc++.h> using namespace std; typedef long lon ...
- [Atcoder Regular Contest 063] Tutorial
Link: ARC063 传送门 C: 将每种颜色的连续出现称为一段,寻找总段数即可 #include <bits/stdc++.h> using namespace std; ,len; ...
- [Atcoder Regular Contest 062] Tutorial
Link: ARC 062 传送门 C: 每次判断增加a/b哪个合法即可 并不用判断两个都合法时哪个更优,因为此时两者答案必定相同 #include <bits/stdc++.h> usi ...
- AtCoder Regular Contest 061
AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...
- AtCoder Regular Contest 094 (ARC094) CDE题解
原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...
- AtCoder Regular Contest 092
AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...
- AtCoder Regular Contest 093
AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...
随机推荐
- JS之document例题讲解1(两张表之间数据转移、日期时间选择、子菜单下拉、用div做下拉菜单、事件总结)
作业一:两个列表之间数据从一个列表移动到另一个列表 <div style="width:600px; height:500px; margin-top:20px"> & ...
- 【转载】Lua脚本语法说明(修订)
原文:http://www.cnblogs.com/ly4cn/archive/2006/08/04/467550.html 挑出来几个 .逻辑运算 and, or, not 其中,and 和 or ...
- bzoj 1503 平衡树
我们可以用一颗平衡树维护每个人的工资,因为工资的变化会影响到后面所有的人,所以我们打一个标签,向平衡树里插入的时候减去这个标签的值,这样代表改变了之后的零点,,这样维护这个标签就好了,输出的时候要加上 ...
- window对象的方法和属性汇总
window对象有以下方法: open close alert confirm prompt setTimeout clearTimeout setInterval clearInterval mov ...
- 子DIV块中设置margin-top时影响父DIV块位置的解决办法?
解决方法: 1.修改父元素的高度,增加padding-top样式模拟(padding-top:1px:常用) 2.为父元素添加overflow:hidden:样式即可(完美) 3.为父元素或者子元素声 ...
- embed标签 阻止点击事件 让父元素处理点击事件
由于规定页面显示的PDF文件要有固定大小,使得页面风格统一 最开始发现了CSS样式pointer-events 写出如下代码,在360急速浏览器急速模式中访问可在点击PDF控件时可跳转页面 <a ...
- 生成应用的快捷方式action,权限
action:"com.android.launcher.action.INSTALL_SHORTCUT" 权限:com.android.launcher.permission.I ...
- querySelector()与querySelectorAll()
1.querySelector() 参数:css选择器 返回匹配指定css选择器元素的第一个子元素 2.querySelectorAll() 参数:css选择器 返回匹配指定css选择器的所有元素
- Java的9种基本数据类型的大小,以及他们的封装类
由于java程序是运行在虚拟机之上的,所以java的基本数据类型的大小是确定的,不会随着操作系统的位数的改变而改变. 在计算机中,存储的是0,1,0,1这样的二进制位,表示为bit,1Byte = 8 ...
- python实战===用python调用jar包(原创)
一个困扰我很久的问题,今天终于解决了.用python调用jar包 很简单,但是网上的人就是乱转载.自己试都不试就转载,让我走了很多弯路 背景:python3.6 32位 + jre 32位 + ...