Educational Codeforces Round 53

Educational Codeforces Round 53

F. Choosing Two Paths(CF 1073F)

题目描述
http://codeforces.com/contest/1073/problem/F

题解
其实就是类似树上最长链的做法,从根开始往下搜,如果一个点有多于一个孩子那它就可能作为起点。
统计出每个点的两个最深的孩子作为两个起点,然后在所有合法点钟找出符合题意的最长链就好了。

代码

#include
#define N 200010
using namespace std;
int n,A,B,C,D,pos,dep[N],f[N],g[N];
int k,la[N],ff[N*2];
struct info{
  int x,y;
  bool operator<(const info &p)const{
    return xdep[f[x]])g[x]=f[x],f[x]=f[e[a].b];
	else if(dep[f[e[a].b]]>dep[g[x]])g[x]=f[e[a].b];
  }
  if(!cnt)f[x]=x;
  if(cnt>=2)
  {
  	info tmp=(info){dep[x],dep[f[x]]+dep[g[x]]-dep[x]*2};
    if(res

G. Yet Another LCP Problem(CF 1073G)

题目描述
http://codeforces.com/contest/1073/problem/G

题解
lcp就是后缀数组中height的区间最小值。所以按照这个思路做就好了。
把a数组和b数组所有数字按照后缀数组的rank排序,从左往右扫一遍,拿个单调栈维护一下最小的height和它覆盖的区间,后再从右往左扫一遍做一样的事情,就好了。
代码能力太差了,这东西写了好久。。。

代码

#include
#define N 200010
#define ll long long
using namespace std;
int n,m,Q,a[N],b[N],q[N],p[N];char s[N];ll ans;
int cnt[N],x[N],y[N],t[N],sa[N],g[N][20],rk[N],height[N];
struct info{
  int x,tp,k;
  bool operator<(const info &p)const{
    if(k)return rk[x]p.tp);
    return rk[x]>rk[p.x]||(x==p.x&&tpj)y[++tot]=sa[i]-j;
    for(int i=1;i<=n;i++)t[i]=x[y[i]];
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++)cnt[t[i]]++;
    for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    for(int i=n;i;i--)sa[cnt[t[i]]--]=y[i];
    tot=2;swap(x,y);x[sa[1]]=1;
    for(int i=2;i<=n;i++)
      x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?tot-1:tot++;
  }
}

void get_height()
{
  for(int i=1;i<=n;i++)rk[sa[i]]=i;
  for(int i=1,j,k=0;i<=n;height[rk[i++]]=k)
    for(k=k?k-1:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
}

void get_rmq()
{
  memset(g,127,sizeof(g));
  for(int i=1;i<=n;i++)g[i][0]=height[i];
  for(int j=1;(1<y)swap(x,y);x++;
  int p=log2(y-x+1);
  return min(g[x][p],g[y-(1<

你可能感兴趣的:(题解,套题总结,——树形dp,数据结构,——后缀数组)