首先因为固定询问长度,所以我们可以将整个长度为n的数列hash成长度为n-k+1的数列,每次询问的序列也hash成一个数,然后询问这个数是不是在某个区间中出现过,这样我们可以根据初始数列的权值建立可持久化线段树,对于每个询问先二分判断是否出现在数列中过,然后再判断是否在区间内出现过。也可以离线将询问和数列建立可持久化线段树,那么直接判断就可以了,但是空间消耗会大些。

  反思:偷懒直接用的map判的是否出现,然后改了hash用long long存之后map_insert没有改,然后就一直WA。

     不知道数据的范围,开大了数组好多。

/**************************************************************
Problem: 3207
User: BLADEVIL
Language: C++
Result: Accepted
Time:6580 ms
Memory:130804 kb
****************************************************************/ //By BLADEVIL
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 500010
#define LL long long using namespace std; struct segment {
int left,right,cnt;
int son[];
segment() {
left=right=cnt=;
memset(son,,sizeof son);
}
}t[*maxn]; struct rec {
int num,key;
LL hash;
rec() {
hash=num=key=;
}
}a[maxn]; int n,m,k,sum,tot;
int rot[maxn];
map<LL,int>tree; bool cmp1(rec x,rec y) {
return x.hash<y.hash;
} bool cmp2(rec x,rec y) {
return x.num<y.num;
} void map_insert(LL x,int y) {
if (tree.find(x)==tree.end()) tree.insert(pair<LL,int>(x,y));
} void build(int &x,int l,int r) {
if (!x) x=++tot;
t[x].left=l; t[x].right=r;
if (l==r) return ;
int mid=t[x].left+t[x].right>>;
build(t[x].son[],l,mid); build(t[x].son[],mid+,r);
} void insert(int &x,int rot,int y) {
if (!x) x=++tot;
t[x].left=t[rot].left; t[x].right=t[rot].right;
if (t[x].left==t[x].right) {
t[x].cnt=t[rot].cnt+;
return ;
}
int mid=t[x].left+t[x].right>>;
if (y>mid) {
t[x].son[]=t[rot].son[];
insert(t[x].son[],t[rot].son[],y);
} else {
t[x].son[]=t[rot].son[];
insert(t[x].son[],t[rot].son[],y);
}
t[x].cnt=t[rot].cnt+;
} int query(int lx,int rx,int y) {
if (t[lx].left==t[lx].right) return t[rx].cnt-t[lx].cnt;
int mid=t[lx].left+t[lx].right>>;
if (y>mid) return query(t[lx].son[],t[rx].son[],y); else return query(t[lx].son[],t[rx].son[],y);
} int main() {
scanf("%d%d%d",&n,&m,&k);
for (int i=;i<=n;i++) scanf("%d",&a[i].key);
n=n-k+;
for (int i=;i<=n;i++)
for (int j=i;j<=i+k-;j++) a[i].hash=a[i].hash*+a[j].key;
for (int i=;i<=n;i++) a[i].num=i;
sort(a+,a+n+,cmp1); sum=; LL cur=a[].hash;
//for (int i=1;i<=n;i++) printf("%d ",a[i].hash); printf("\n");
for (int i=;i<=n;i++)
if (a[i].hash==cur) a[i].key=sum; else cur=a[i].hash,a[i].key=++sum;
sort(a+,a+n+,cmp2);
//for (int i=1;i<=n;i++) printf("%d ",a[i].key); printf("\n");
for (int i=;i<=n;i++) map_insert(a[i].hash,a[i].key);
build(rot[],,sum);
for (int i=;i<=n;i++) insert(rot[i],rot[i-],a[i].key);
while (m--) {
int l,r; scanf("%d%d",&l,&r); if (r>n) r=n;
LL ha=;
for (int i=;i<=k;i++) {
int x; scanf("%d",&x);
ha=ha*+x;
}
map<LL,int>::iterator p=tree.find(ha);
if (p==tree.end()) {
printf("Yes\n");
continue;
}
int y=p->second;
if (query(rot[l-],rot[r],y)>) printf("No\n"); else printf("Yes\n");
//printf("%d\n",query(rot[l-1],rot[r],y));
}
return ;
}

bzoj 3207 可持久化线段树的更多相关文章

  1. bzoj 3207 可持久化线段树+hash

    这道题要看出来这个做法还是比较容易说一下细节 1.因为要用hash的区间值域来建树,而hash为了不冲突要开的很大,所以值域就会比较的大,不过这道题好的一点是没有修改,所以直接离散一下就会小很多 2. ...

  2. bzoj 3123 可持久化线段树启发式合并

    首先没有连边的操作的时候,我们可以用可持久化线段树来维护这棵树的信息,建立权值可持久化线段树,那么每个点继承父节点的线段树,当询问为x,y的时候我们可以询问rot[x]+rot[y]-rot[lca( ...

  3. bzoj 3524 可持久化线段树

    我们可以先离散化,然后建立权值的可持久化线段树,记录每个数出现的次数,对于区间询问直接判断左右儿子的cnt是不是大于(r-k+1)/2,然后递归到最后一层要是还是大于就有,否则不存在. 反思:挺简单一 ...

  4. BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 9280  Solved: 2421 ...

  5. [BZOJ 3207] 花神的嘲讽计划Ⅰ【Hash + 可持久化线段树】

    题目链接:BZOJ - 3207 题目分析 先使用Hash,把每个长度为 k 的序列转为一个整数,然后题目就转化为了询问某个区间内有没有整数 x . 这一步可以使用可持久化线段树来做,虽然感觉可以有更 ...

  6. [BZOJ 3218] A + B Problem 【可持久化线段树 + 网络流】

    题目连接:BZOJ - 3218 题目分析 题目要求将 n 个点染成黑色或白色,那么我们可以转化为一个最小割模型. 我们规定一个点 i 最后属于 S 集表示染成黑色,属于 T 集表示染成白色,那么对于 ...

  7. BZOJ.4771.七彩树(可持久化线段树)

    BZOJ 考虑没有深度限制,对整棵子树询问怎么做. 对于同种颜色中DFS序相邻的两个点\(u,v\),在\(dfn[u],dfn[v]\)处分别\(+1\),\(dfn[LCA(u,v)]\)处\(- ...

  8. BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)

    BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...

  9. BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)

    BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...

随机推荐

  1. 第二章 持续集成jenkins工具使用之系统基本设置

    Jenkin系统初始化成功后,会进入用户设置页面,设置用户信息后即可进入系统,如果没有设置用户,jenkins系统默认的用户是admin,密码administrator 1.1         Con ...

  2. 图像检测算法Halcon 10的使用

    安装完成HALCON之后,在VS项目中添加动态链接库配置项目,并修改此项目属性的包含目录.库目录和链接器.

  3. 《Effective C#》快速笔记(三)- 使用 C# 表达设计

    目录 二十一.限制类型的可见性 二十二.通过定义并实现接口替代继承 二十三.理解接口方法和虚方法的区别 二十四.用委托实现回调 二十五.用事件模式实现通知 二十六.避免返回对内部类对象的引用 二十七. ...

  4. WPF实例,以getFiles()获取文件夹,treeview的应用

    读取电脑硬盘根目录添加到TreeView控件 foreach (DriveInfo item in System.IO.DriveInfo.GetDrives()) { if(item.ToStrin ...

  5. C++除法运算 // 静态断言

    1.C++中"/"运算:对两个整数做除法,结果仍为整数,如果它的商包含小数部分,则小树部分会被截除. C++ Primer 第五章 P130 2.静态断言(static_asser ...

  6. [洛谷P4721]【模板】分治 FFT_求逆

    题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:分治$FFT$博客,发现 ...

  7. [HNOI2012]排队 组合数

    公式:A(n,n)*A(n+1,2)*A(n+3,m) + A(n,n)*C(m,1)*A(2,2)*C(n+1,1)*A(n+2,m-1) 分情况讨论推出公式 前者为无论何时都合法的,后者为先不合法 ...

  8. 弱校的ACM奋斗史

    这是一篇老文章,不过由于无法找到最初的发文地址,这里就不能粘贴原文网址了.本站转载此文与ACMer们共勉.感谢acmerfight供稿. 题解:还记得2年前的一个晚上,我和一个女孩一起写完了这篇文章. ...

  9. 【初级算法】2.买卖股票的最佳时机 II

    题目: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能同时参与多笔交易(你必 ...

  10. 使用canvas画一个雷达效果图的特效代码

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...