题意:

给定n个字符串S1,S2,S3,...,Sn,把它们排序

设排序结果为Sp1,Sp2,Sp3,...,Spn

现在给定q个任务,每个任务的格式都是"要求在排序结果中Sa恰好在Sb前一个"

你排出的串满足第i个任务,就可以得到2^i(2的i次方)的奖励

现在有两个问题:

1.求相邻两项LCP平方和W的最大值

2.求出当W最大时能获得最多奖励的排序结果

数据&部分分:

对于 10%的数据,n ≤ 10,q = 1, 每个字符串的长度不超过 50; 
对于 20%的数据,n ≤ 50,q = 1, 每个字符串的长度不超过 50; 
对于 50%的数据,n ≤ 1000,q ≤ 1000, 每个字符串的长度不超过 1000; 
对于 70%的数据,任意字符串不为其他任何一个字符串的前缀; 
对于100%的数据, n ≤ 40 000, q ≤ 100 000, 每个字符串的长度不超过10 000; 
对于 100%的数据,所有字符串的长度和不超过 200000。

bzoj坑爹啊,没有数据范围,还好Codevs上有

思路:

嗯,WJMZBMR远古巨神的神题,肯定不是我等一般人能做出来的
当然,在我有理有据的乱搞之前,我们先要确定这道题考的是啥
多个串,很像AC自动机,但LCP又跟AC自动机联系不起来,
苦苦思索2晚上无果后我的思路到了关键的一点:陈立杰在2012年的《后缀自动机讲稿》上有这么一句话

然后我就确定了:不会有后缀数据结构,毕竟CTSC也不太可能会出后缀数组
好,那么字符串还剩下什么数据结构呢
我们看数据范围的最后一条
答案脱口而出:Trie树!
对,就是Trie树大暴力

整理一下思路:我们明确两个大方向
(1)根据历史的进程,这道题一定是Trie树
(2)Trie树上的LCP,其实就是LCA的深度

好,现在我们开始做题
我们写一个动态Trie动态维护排序信息

别急,先打打暴力,看看有没有什么特殊性质
于是我在数学课上手算了4组数据发现
第一问是tm逗你玩的,W最大的情况是"字典序"
本来想着dp的我抱头痛哭

严谨证明的话...不太会

可能是在Trie树上搞个路径统计?

可以知道的是:一个字符串排列就相当于Trie树上一条从根出发回到根的路径

不知道,反正这一问在Trie树上按字典序dfs一下就好了

我们看第二问
第二问会发现,越往后奖励越多,所以我们考虑操作离线倒序,如果当前任务可以取就取到,然后更改Trie树上的路径(我就是在这yy出了LinkCutTrie的)

于是开始了漫长的手推

草稿纸都用了一张多,最后发现可以弄一个Trie链剖分+树套树

看了看前人的代码长度大概都是这么做的吧

然后在纸上写了很多乱七八糟的东西

...要滚去写作业了,幸运的是找到了曾经的题解

也算是看了一点点吧

毕竟还是个没学上的蒟蒻不可能一下子A掉CTSC的是不是?

放个链接吧

https://wenku.baidu.com/view/d6e7e02b647d27284b73516a.html?from=search

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
const int maxn=;
const int maxq=;
int n,q,dfn;
int x[maxq],y[maxq];
char SS[maxn];
struct Trie
{
Trie *ch[];
int Size,dep,rnk;
Trie *prev,*next;
Trie *first,*last;
Trie *father,*top;
Trie()
{
memset(ch,,sizeof(ch));
Size=;
father=;
prev=next=first=last=;
}
Trie *pre()
{
Trie *now;
for(now=this;now->prev;now=now->prev);
return now;
}
Trie *suf()
{
Trie *now;
for(now=this;now->next;now=now->next);
return now;
}
Trie *insert(int val)
{
Trie* &now=ch[val];
if (now==)
{
now=new Trie;
now->father=this;
Size++;
}
return now;
}
int count()
{
Trie *now=pre();
int cnt=;
while(now)
{
++cnt;
now=now->next;
}
return cnt;
}
bool find(Trie*o)
{
Trie *now=pre();
while(now)
{
if(now==o)return true;
now=now->next;
}
return false;
}
bool canFirst(Trie*c)
{
if (c==first)return true;
if (first != || c->prev != )return false;
if (c->suf()==last && c->count()!=Size)return false;
return true;
}
bool canLast(Trie*c)
{
if (c == last)return true;
if (last!= || c->next!=)return false;
if (c->pre()==first && c->count()!=Size)return false;
return true;
}
bool canNext(Trie*c1,Trie*c2)
{
if (c1->next==c2)return true;
if (c1->next!= || c2->prev!=)return false;
if (c1==last || c2==first)return false;
if (c1->find(c2))return false;
if (c1->pre()==first && c2->suf()==last && c1->count()+c2->count()<Size)return false;
return true;
}
void dfs(int de)
{
rnk=dfn++;
dep=de;
if(father==) top=;
else if(father->Size>)top=father;
else top=father->top;
for(int i=;i<;i++)if(ch[i]!=)ch[i]->dfs(dep+);
}
};
int todolis[maxq];
Trie *es[maxn],*ed[maxn],*rt;
Trie *getLCA(Trie *a, Trie *b)
{
while("woxihuan_keduoli")
{
if(a==b)return a;
if(a==rt || b==rt)return rt;
if( (a->top->dep) < (b->top->dep) )swap(a,b);
a=a->top;
}
}
void set(Trie *a,Trie *b)
{
Trie *l=getLCA(a,b);
while(a->top!=l)
{
Trie*fa=a->top;
fa->last=a;
a=fa;
}
while(b->top!=l)
{
Trie*fa=b->top;
fa->first=b;
b=fa;
}
a->next=b,b->prev=a;
}
bool check(Trie *a, Trie *b)
{
Trie *l=getLCA(a, b);
while(a->top!=l)
{
Trie*fa=a->top;
if(!fa->canLast(a))return false;
a=fa;
}
while(b->top!=l)
{
Trie*fa=b->top;
if(!fa->canFirst(b))return false;
b=fa;
}
if(!l->canNext(a,b))return false;
return true;
}
bool cmp(Trie*a, Trie*b){return (a->rnk) < (b->rnk);}
ll ans,cnt;
int main()
{
scanf("%d%d",&n,&q);
rt=new Trie;
for(int i=;i<n;i++)
{
scanf("%s",SS);
int len=strlen(SS);
Trie *temp=rt;
for(int j=;j<len;j++)temp=temp->insert(SS[j]-'a'+);
temp=temp->insert();
ed[i]=temp;
}
ll ans=;
rt->dfs();
for(int i=;i<q;i++) scanf("%d%d",&x[i],&y[i]),--x[i],--y[i];
for(int i=q-;i>=;i--)
if(check(ed[x[i]],ed[y[i]]))
{
set(ed[x[i]],ed[y[i]]);++cnt;todolis[i]=;
}
for(int i=;i<n;i++)es[i]=ed[i];
sort(es,es+n,cmp);
ll tmp;
for(int i=;i<n-;i++)
{
tmp=getLCA(es[i],es[i+])->dep;
ans+=tmp*tmp;
}
printf("%lld\n%lld\n",ans,cnt);
for(int i=;i<q;i++)if(todolis[i])printf("%d ",i+);
return ;
}

OI加油 期末加油

bzoj2309 CTSC2011 字符串重排的更多相关文章

  1. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  2. uvaoj1339 - Ancient Cipher(思维题,排序,字符串加密)

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  3. UVa 1339 Ancient Cipher --- 水题

    UVa 1339 题目大意:给定两个长度相同且不超过100个字符的字符串,判断能否把其中一个字符串重排后,然后对26个字母一一做一个映射,使得两个字符串相同 解题思路:字母可以重排,那么次序便不重要, ...

  4. codeforces 1093 题解

    12.18 update:补充了 $ F $ 题的题解 A 题: 题目保证一定有解,就可以考虑用 $ 2 $ 和 $ 3 $ 来凑出这个数 $ n $ 如果 $ n $ 是偶数,我们用 $ n / 2 ...

  5. LOJ2484 CEOI2017 Palindromic Partitions DP、回文树

    传送门 当我打开Luogu题解发现这道题可以Hash+贪心的时候我的内心是崩溃的-- 但是看到这道题不都应该认为这是一道PAM的练手好题么-- 首先把原字符串重排为\(s_1s_ks_2s_{k-1} ...

  6. 给定两个字符串 s 和 t,它们只包含小写字母。 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。 请找出在 t 中被添加的字母。

    给定两个字符串 s 和 t,它们只包含小写字母.字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母.请找出在 t 中被添加的字母. 示例: 输入: s = "abcd" ...

  7. 小b重排字符串

    2485 小b重排字符串 2 秒 262,144 KB 5 分 1 级题   小b有一个字符串S,现在她希望重排列S,使得S中相邻字符不同. 请你判断小b是否可能成功. 样例解释:将"aab ...

  8. 51nod 2485 小b重排字符串

    小b有一个字符串S,现在她希望重排列S,使得S中相邻字符不同. 请你判断小b是否可能成功. 样例解释:将"aab"重排为"aba"即可. 收起   输入 输入一 ...

  9. 【LeetCode】358.K 距离间隔重排字符串

    358.K 距离间隔重排字符串 知识点:哈希表:贪心:堆:队列 题目描述 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少 ...

随机推荐

  1. robotframe使用之滚动条

    方法一:Excute JavaScript window.scrollTo(0,document.body.scrollHeight); 方法二:Execute javascript document ...

  2. c语言中结构体指针

    1.指向结构体的指针变量: C 语言中->是一个总体,它是用于指向结构体,如果我们在程序中定义了一个结构体,然后声明一个指针变量指向这个结构体.那么我们要用指针取出结构体中的数据.就要用到指向运 ...

  3. QTreeWidget 的用法

    Qt QTreeWidget 新建一个Qt Widgets Application,拖拽一个Tree Widget 到 ui 界面上,最后实现的效果如下: 添加代码 //test.h //在头文件里添 ...

  4. 个人笔记-CSS

    http://localhost:1081/sdfsdfs/config-browser/actionNames.action 超出容器文字隐藏 .hiddenoverflowtext { width ...

  5. matlab中文显示乱码:控制台上的,编辑器的,图片中的

    问题:matlab脚本与函数文件的中文注释显示乱码. 环境:matlab R2016a.Windows 10 home. 解决方案: step1 检查locale值 matlab命令行键入命令 fea ...

  6. SQLServer -- SQL Server Database Error: 内部 SQL Server 错误

    报表在SQLserver2008运行统计正常,但是在SQLserver2000运行报错,SQL直接执行报:内部 SQL Server 错误. 不断的排查,最终得到的结论是:SQLserver2000似 ...

  7. System.TypeLoadException: Could not load type 'System.IO.Compression.CompressionLevel' from assembly 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

    1.提示错误信息: zipSystem.TypeLoadException: Could not load type 'System.IO.Compression.CompressionLevel' ...

  8. eclipse转到IntelliJ IDEA 2017.1入坑指南

    最近准备从eclipse转到IDE上去,由于eclipse占用的内存太大,而且IDE看着逼格还是比较大的,在转移项目的时候遇到好多的坑呀!在这里记录一下 关于:2017.1版本 之前装的是2016的版 ...

  9. 基于EasyNVR二次开发实现自己的摄像机IPC/NVR无插件化直播解决方案

    在之前的博客中<基于EasyNVR实现RTSP/Onvif监控摄像头Web无插件化直播监控>,我们已经比较多的描述EasyNVR所实现的功能,这些也在方案地址:http://www.eas ...

  10. 《转》使用nginx和php实时产生缩略图

    在做自动静态化的时候,突然想到下面这个场景,也给出了解决方法.亲,真的很实用,耐心看下去.     当我从后台上传一个截图之后,480*800的截图之后,当时就没有压缩出320*480的小缩略图.好吧 ...