【AtCoder】 ARC 097
link
C-K-th Substring
题意:找出已知串中第\(k\)大的子串,子串相同的不算
\(k\)好小啊,要怎么做啊
不是【Tjoi2015】弦论吗
算了,直接SAM吧
#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"\n"
#define dbg3(x) cerr<<#x<<"\n"
using namespace std;
#define reg register
const int MN=1e4+4;
char s[5005];int K;
int c[MN][26],step[MN],val[MN],fa[MN],siz[MN],v[MN],rk[MN];
int last,cnt,n;
inline void init()
{
last=cnt=1;memset(c,0,sizeof c);
reg int i;
for(i=1;i<n<<1;++i) val[i]=step[i]=fa[i]=0;
}
void Insert(int x)
{
int p=last,np=++cnt;step[np]=step[p]+1;val[np]=1;
for(;p&&!c[p][x];p=fa[p]) c[p][x]=np;
if(!p) fa[np]=1;
else
{
int q=c[p][x];
if(step[q]==step[p]+1) fa[np]=q;
else
{
int nq=++cnt;step[nq]=step[p]+1;
memcpy(c[nq],c[q],sizeof c[q]);
fa[nq]=fa[q];fa[np]=fa[q]=nq;
for(;c[p][x]==q;p=fa[p]) c[p][x]=nq;
}
}
last=np;
}
inline void work()
{
reg int i,j;
for(i=1;i<=cnt;++i) ++v[step[i]];
for(i=1;i<=n;++i) v[i]+=v[i-1];
for(i=1;i<=cnt;++i) rk[v[step[i]]--]=i;
for(i=2;i<=cnt;++i) val[i]=siz[i]=1;
val[1]=siz[1]=0;
for(i=cnt;i;--i)for(j=0;j<26;++j)
if(c[rk[i]][j])siz[rk[i]]+=siz[c[rk[i]][j]];
}
char ans[MN];int len;
inline void dfs(int x,int k)
{
if(k<=val[x]) return;k-=val[x];
reg int i;
for(i=0;i<26;++i)
if(k>siz[c[x][i]]) k-=siz[c[x][i]];
else {ans[len++]=i+'a',dfs(c[x][i],k);break;}
}
int main()
{
reg int i,k;
scanf("%s%d",s+1,&k);n=strlen(s+1);
init();
for(i=1;i<=n;++i) Insert(s[i]-'a');
work();
dfs(1,k),printf("%s",ans);
return 0;
}
D-Equals
题意:一个排列,一些位置对可任意交换,最大化\(p_i=i\)的\(i\)的数量
并查集把每个可以互相通达的部分找出来即可
#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"\n"
#define dbg3(x) cerr<<#x<<"\n"
using namespace std;
#define reg register
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MN=1e5+5;
int N,M,p[MN];
int fa[MN];
int getf(int x){return x==fa[x]?x:fa[x]=getf(fa[x]);}
int main()
{
N=read(),M=read();
reg int i,x,y;
for(i=1;i<=N;++i) p[read()]=i,fa[i]=i;
for(i=1;i<=M;++i)
{
x=read(),y=read();
if(getf(x)^getf(y)) fa[getf(x)]=fa[getf(y)];
}
int ans=0;
for(i=1;i<=N;++i) ans+=(getf(i)==getf(p[i]));
return 0*printf("%d\n",ans);
}
E-Sorted and Sorted
题意:\(N\)个黑球\(N\)个白球,交换相邻的球使最终排列满足黑白两色均升序,最小化交换次数
dp,相当于对球的序列进行重新标号,最小化逆序对数
可以设\(f_{i,j}\)表示前\(i\)个白球和前\(j\)个黑球重标号后的最小逆序对数,转移时枚举最后一个球的颜色
#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"\n"
#define dbg3(x) cerr<<#x<<"\n"
using namespace std;
#define reg register
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MN=2005;
int N,f[MN][MN],g[2][MN][MN],T[2][MN];
void C(int x,int y){for(;x<=N;x+=(x&(-x)))T[y][x]++;}
int G(int x,int y){int r=0;for(;x;x-=(x&(-x)))r+=T[y][x];return r;}
int main()
{
N=read();
reg int i,j;char c;
for(i=1;i<=N*2;++i)
{
scanf("%c",&c);
if(c=='W')
{
int x=read();C(x,0);
for(j=0;j<=N;++j) g[0][x][j]=x+j-G(x,0)-G(j,1);
}
else
{
int x=read();C(x,1);
for(j=0;j<=N;++j) g[1][j][x]=x+j-G(x,1)-G(j,0);
}
}
for(i=1;i<=N;++i) f[i][0]=f[i-1][0]+g[0][i][0];
for(i=1;i<=N;++i) f[0][i]=f[0][i-1]+g[1][0][i];
for(i=1;i<=N;++i)for(j=1;j<=N;++j)
f[i][j]=min(f[i-1][j]+g[0][i][j],f[i][j-1]+g[1][i][j]);
return 0*printf("%d\n",f[N][N]);
}
F-Monochrome Cat
题意:一棵黑白两色的树,树上任意选择一个点开始移动,每次可以耗费一单位时间来改变当前点的颜色或是耗费一单位时间来进行一次移动,使得所有都是黑色的最小时间
把黑色部分给去掉,使得所有度数为一的点的颜色都是白色,这时,路径必然经过每个点,可以发现每条边最多经过两次,先假设每条边都经过了两次,而经过一次的边必然为一条连续的路径,简单树d可以完成。
#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"\n"
#define dbg3(x) cerr<<#x<<"\n"
using namespace std;
#define reg register
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MN=1e5+5,inf=0x7fffffff;
int N;
bool c[MN];
struct edge{int to,nex;}e[MN<<1];
int en,hr[MN];
void ins(int x,int y)
{
e[++en]=(edge){y,hr[x]};hr[x]=en;
e[++en]=(edge){x,hr[y]};hr[y]=en;
}
int sw[MN],fa[MN],rt,sW;
void dfs1(int x,int f=0)
{
reg int i;sw[x]=c[x];fa[x]=f;
for(i=hr[x];i;i=e[i].nex)if(e[i].to^f)dfs1(e[i].to,x),sw[x]+=sw[e[i].to];
if(sw[x]==sW&&!rt)rt=x;
}
int ans,son[MN],deg[MN];
void dfs2(int x)
{
if(!sw[x])return;++son[fa[x]];if(x!=rt)ans+=2;
for(int i=hr[x];i;i=e[i].nex)if(e[i].to^fa[x])dfs2(e[i].to);
ans+=(deg[x]=son[x]+c[x]+(x!=rt))&1;deg[x]=deg[x]&1?1:-1;
}
int dp[MN][2];
#define fi first
#define se second
void dfs3(int x)
{
reg int i;
if(!sw[x])return;pair<int,int> p;p.fi=p.se=0;
for(i=hr[x];i;i=e[i].nex)if(e[i].to!=fa[x]&&sw[e[i].to])
{
dfs3(e[i].to);
dp[x][0]=max(dp[x][0],dp[e[i].to][0]);
dp[x][1]=max(dp[x][1],deg[x]+1+dp[e[i].to][1]);
}
if(son[x]>=2)
{
for(i=hr[x];i;i=e[i].nex)if(e[i].to!=fa[x]&&sw[e[i].to])
{
int v=dp[e[i].to][1];
if(v>p.fi)p.se=p.fi,p.fi=v;
else if(v>p.se)p.se=v;
}
dp[x][0]=max(dp[x][0],deg[x]+1+p.fi+p.se);
}
dp[x][0]=max(dp[x][0],dp[x][1]);
}
char s[MN];
int main()
{
N=read();reg int i,x;
for(i=1;i<N;++i) x=read(),ins(x,read());
scanf("%s",s+1);
for(i=1;i<=N;++i) c[i]=s[i]=='W',sW+=c[i];
dfs1(1);dfs2(rt);dfs3(rt);
return 0*printf("%d\n",ans-dp[rt][0]);
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
【AtCoder】 ARC 097的更多相关文章
- 【AtCoder】ARC 081 E - Don't Be a Subsequence
[题意]给定长度为n(<=2*10^5)的字符串,求最短的字典序最小的非子序列字符串. http://arc081.contest.atcoder.jp/tasks/arc081_c [算法]字 ...
- 【Atcoder】ARC 080 E - Young Maids
[算法]数学+堆 [题意]给定n个数的排列,每次操作可以取两个数按序排在新序列的头部,求最小字典序. [题解] 转化为每次找字典序最小的两个数按序排在尾部,则p1和p2的每次选择都必须满足:p1在当前 ...
- 【Atcoder】ARC 080 F - Prime Flip
[算法]数论,二分图最大匹配 [题意]有无限张牌,给定n张面朝上的牌的坐标(N<=100),其它牌面朝下,每次操作可以选定一个>=3的素数p,并翻转连续p张牌,求最少操作次数使所有牌向下. ...
- 【AtCoder】 ARC 096
link C-Half and Half 题意:三种pizza,可以花\(A\)价钱买一个A-pizza,花\(B\)价钱买一个B-pizza,花\(C*2\)价钱买A-pizza和B-pizza各一 ...
- 【AtCoder】 ARC 098
link C-Attention 题意:一个字符队列,每个位置是\(W\)或\(E\),计算最小的修改数量,使得存在一个位置,它之前的都是\(E\),之后的都是\(F\) #include<bi ...
- 【AtCoder】 ARC 099
link C-Minimization 枚举覆盖\(1\)的区间,两边的次数直接算 #include<bits/stdc++.h> #define ll long long #define ...
- 【AtCoder】 ARC 100
link C-Linear Approximation 给出\(N\)个数\(A_1,A_2,...,A_N\) ,求一个数\(d\),最小化\(\sum_{i=1}^N|A_i-(d+i)|\) 把 ...
- 【AtCoder】 ARC 101
link 搬来了曾经的题解 C-Candles 题意:数轴上有一些点,从原点开始移动到达这些点中的任意\(K\)个所需要的最短总路程 \(K\)个点必然是一个区间,枚举最左边的就行了 #include ...
- 【AtCoder】 ARC 102
link C-Triangular Relationship 发现要么全部是\(K\)的倍数,要么全部是模\(K\)余\(K/2,(K=2n)\) #include<bits/stdc++.h& ...
随机推荐
- Jackson动态JSON处理
https://www.baeldung.com/jackson-mapping-dynamic-object https://www.baeldung.com/jackson-deserializa ...
- JCEF-鼠标右键菜单
为鼠标添加自定义菜单,比较简单,实现一个Handler就行 Hanler实现类 public class MenuHandler extends CefContextMenuHandlerAdapte ...
- 字典排序MD5生成代码
/* * Project: payment.framework * * File Created at 2017年12月23日 * * Copyright 2016 CMCC Corporation ...
- SpringBoot2.x的Maven依赖配置
本篇主要说明以下内容: 1.SpringBoot2.x中Maven的配置内容,即:pom.xml的内容说明 1 Maven依赖的配置方式 使用Maven来配置SpringBoot2.x,有两种方式: ...
- 普通脚本调用django程序
#其他的脚本调用django中的程序 import os if __name__ == "__main__": #添加django项目的环境 os.environ.setdefau ...
- 分享一篇最近新写的jquery注册页面表单校验的程序,仅供参考
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Jquery学习笔记,全面实用,需要的可以留下邮箱,给大家发原稿文档
JQuery 第一章:Jquery概念介绍 1.1 Jquery介绍 (1)并不是一门新语言.将常用的.复杂的操作进行函数化封装,直接调用,大大降低了使用JavaScript的难度,改变了使用Java ...
- 【使用DIV+CSS重写网站首页案例】CSS选择器
使用表格<table></table>对网站首页进行布局有缺陷,不能拖动版块,不灵活. DIV Div是一个html的标签,单独使用没有意义,必须结合CSS使用: 是一个块级元 ...
- Mincut 最小割 (BZOJ1797+最小割+tarjan)
题目链接 传送门 思路 根据题目给定的边跑一边最大流,然后再在残留网络上跑\(tarjan\). 对于每一条边有: 如果它是非满边,那么它一定不是最小割集里面的边: 如果\(c[u[i]] \not= ...
- 《MVC架构下网站的设计与实现》论文笔记(十八)
标题:MVC架构下网站的设计与实现 一.基本信息 时间:2017 来源:广东海洋大学数学与计算机学院 关键词:网站设计:MVC 框架:数据库:网络安全 二.研究内容 1.系统的整体架构设计(以广东海洋 ...