思路:

网上的题解有AC自动机的,有trie树的,还有(乱搞?)的

首先把输入的那n个串按照字典序排序,

把n个串翻转以后再按照字典序排序

这样我们发现, 查的前缀在字典序排序后是一段区间,

查的后缀翻转一下在翻转后的字典序排序以后也是一段区间

这样如果不考虑重叠的问题,就是一个简单的二维数点问题,一维排序,一维线段树即可解决

如果有重叠的问题,我们需要搞出来每个字符串的长度,使给出的前缀长+后缀长>=原字符串长度

此时题目变成了三维偏序,排序后树套树即可。

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=;
int cases,n,q,root[N<<],cnt,tree[N*],lson[N*],rson[N*];
struct Node{string str;int id,len;}X[N],Y[N],tmp;
bool operator<(Node a,Node b){return a.str<b.str;}
struct Pnt{int x,y,z;}p[N];
struct Ask{int xl,xr,yl,yr,z,id,ans;}ask[N];
bool cmp1(Pnt a,Pnt b){return a.z>b.z;}
bool cmp2(Ask a,Ask b){return a.z>b.z;}
bool cmp3(Ask a,Ask b){return a.id<b.id;}
void Insert(int l,int r,int &pos,int wei){
if(!pos)pos=++cnt;tree[pos]++;
if(l==r)return;
int mid=(l+r)>>;
if(mid>=wei)Insert(l,mid,lson[pos],wei);
else Insert(mid+,r,rson[pos],wei);
}
void insert(int l,int r,int pos,int num,int wei){
Insert(,n,root[pos],wei);
if(l==r)return;
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
if(mid<num)insert(mid+,r,rson,num,wei);
else insert(l,mid,lson,num,wei);
}
int Query(int l,int r,int pos,int L,int R){
if(l>=L&&r<=R)return tree[pos];
int mid=(l+r)>>;
if(mid<L)return Query(mid+,r,rson[pos],L,R);
else if(mid>=R)return Query(l,mid,lson[pos],L,R);
else return Query(l,mid,lson[pos],L,R)+Query(mid+,r,rson[pos],L,R);
}
int query(int l,int r,int pos,int xl,int xr,int yl,int yr){
if(l>=xl&&r<=xr)return Query(,n,root[pos],yl,yr);
int mid=(l+r)>>,lson=pos<<,rson=pos<<|;
if(mid<xl)return query(mid+,r,rson,xl,xr,yl,yr);
else if(mid>=xr)return query(l,mid,lson,xl,xr,yl,yr);
else return query(l,mid,lson,xl,xr,yl,yr)+query(mid+,r,rson,xl,xr,yl,yr);
}
int main(){
ios::sync_with_stdio(false);
cin>>cases;
while(cases--){
memset(tree,,sizeof(int)*(cnt+));
memset(lson,,sizeof(int)*(cnt+));
memset(rson,,sizeof(int)*(cnt+));
memset(root,,sizeof(root));cnt=;
cin>>n>>q;
for(int i=;i<=n;i++)cin>>X[i].str;
sort(X+,X++n);
for(int i=;i<=n;i++)X[i].id=i,X[i].len=X[i].str.length();
for(int i=;i<=n;i++)Y[i]=X[i];
for(int i=;i<=n;i++)reverse(Y[i].str.begin(),Y[i].str.end());
sort(Y+,Y++n);
for(int i=;i<=n;i++)p[i].x=Y[i].id,p[i].y=i,p[i].z=Y[i].len;
for(int i=;i<=q;i++){
string pre,suf;cin>>pre>>suf;
ask[i].id=i;tmp.str=pre;
ask[i].xl=lower_bound(X+,X++n,tmp)-X;
tmp.str=pre,tmp.str.push_back('z'+);
ask[i].xr=lower_bound(X+,X++n,tmp)-X-;
tmp.str=suf,reverse(tmp.str.begin(),tmp.str.end());
ask[i].yl=lower_bound(Y+,Y++n,tmp)-Y;
tmp.str.push_back('z'+);
ask[i].yr=lower_bound(Y+,Y++n,tmp)-Y-;
ask[i].z=pre.size()+suf.size();
}
sort(p+,p++n,cmp1);sort(ask+,ask++q,cmp2);
int tt=;
for(int i=;i<=q;i++){
while(p[tt].z>=ask[i].z&&tt<=n)insert(,n,,p[tt].x,p[tt].y),tt++;
if(ask[i].xl>ask[i].xr||ask[i].yl>ask[i].yr){ask[i].ans=;continue;}
ask[i].ans=query(,n,,ask[i].xl,ask[i].xr,ask[i].yl,ask[i].yr);
}sort(ask+,ask++q,cmp3);
for(int i=;i<=q;i++)cout<<ask[i].ans<<endl;
}
}

HDU 6096 树套树的更多相关文章

  1. hdu 4417 Super Mario/树套树

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意很简单,给定一个序列求一个区间 [L, R,]中小于等于H的元素的个数. 好像函数式线段树可 ...

  2. hdu 4819 Mosaic 树套树 模板

    The God of sheep decides to pixelate some pictures (i.e., change them into pictures with mosaic). He ...

  3. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

  4. BZOJ4170 极光(CDQ分治 或 树套树)

    传送门 BZOJ上的题目没有题面-- [样例输入] 3 5 2 4 3 Query 2 2 Modify 1 3 Query 2 2 Modify 1 2 Query 1 1 [样例输出] 2 3 3 ...

  5. bzoj3262: 陌上花开(树套树)

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  6. bzoj3295: [Cqoi2011]动态逆序对(树套树)

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  7. BZOJ 3110 k大数查询 & 树套树

    题意: 有n个位置,每个位置可以看做一个集合,现在要求你实现一个数据结构支持以下功能: 1:在a-b的集合中插入一个数 2:询问a-b集合中所有元素的第k大. SOL: 调得火大! 李建说数据结构题能 ...

  8. BZOJ 3110 树套树 && 永久化标记

    感觉树套树是个非常高深的数据结构.从来没写过 #include <iostream> #include <cstdio> #include <algorithm> ...

  9. 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树套树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1901 这题调了我相当长的时间,1wa1a,我是第一次写树套树,这个是树状数组套splay,在每个区间 ...

随机推荐

  1. NodeJS+MongoDB+AngularJS+Bootstrap书店示例

    目录 一.Bootstrap 1.1.添加引用 1.2.在页面中使用BootStrap 1.3.可视化布局 二.使用MongoDB创建数据库 2.1.启动MongoDB数据库 2.2.启动数据库GUI ...

  2. 【c++】动态内存

    静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.它主要存放静态数据.全局数据和常量.注意:const常量在定义时必须初始化 栈区:在执行函数时,函数内局部变量的存储单 ...

  3. NODE安装N管理出错

    Windows不支持,反正我在Linux上用过,从此脱离Win坑!

  4. js获取get传递的值

    <script language="javascript" src="js/jquery-1.9.0.min.js"></script> ...

  5. 【C#】无损转换Image为Icon 【C#】组件发布:MessageTip,轻快型消息提示窗 【C#】给无窗口的进程发送消息 【手记】WebBrowser响应页面中的blank开新窗口及window.close关闭本窗体 【手记】调用Process.EnterDebugMode引发异常:并非所有引用的特权或组都分配给呼叫方 【C#】DataRowState演变备忘

    [C#]无损转换Image为Icon 如题,市面上常见的方法是: var handle = bmp.GetHicon(); //得到图标句柄 return Icon.FromHandle(handle ...

  6. 大数据处理之道 (htmlparser获取数据&lt;一&gt;)

    一:简单介绍 (1)HTML Parser是一个用于解析Html的Java的库.可採用线性或嵌套两种方式.主要用于网页的转换或提取,他有一些特性:过滤器filter,遍历器visitors,通常的标签 ...

  7. JavaScript操作符(关系操作符、相等操作符和条件操作符)

    关系操作符用于对两个值进行比较,返回一个布尔值.关系操作符包括大于(>),小于(<),大于等于(>=),小于等于(<=).当关系操作符用于非数值时,也要先进行数值的转换.如 v ...

  8. [IT学习]学习Python过程需要记忆的一些坑

    1.列表的引用和复制 A byte of Python 中文4.05c版本85页 单纯对列表进行引用,则列表指向同一对象. 如果你需要复制一份全新的拷贝,则需要通过切片操作. 2.仅有一个元素的元组, ...

  9. 不等式数列 DP

    度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 '>' 和 '<' )使其成为一个合法的不等式数列.但是现在度度熊手中只有 ...

  10. C 项目案例实践(1)数据结构之链表(0)

    链表是通过一组任意的存储单元来存储线性表中的数据元素的,那么怎样表示出数据元素之间的线性关系呢?为建立数据元素之间的线性关系,对每个数据元素ai,除了存放数据元素的自身信息ai之外,还需要存放和ai一 ...