Fence(codeforces 232D)
题意:
对于给定的a[1..n],定义区间[s,t]和[x,y]"匹配"当且仅当下列条件同时满足:
1. t-s=y-x,即长度相同。
3. t<x或s>y,即两区间没有交。
2. 对任0<=i<=t-s,有a[s]+a[x]=a[s+i]+a[x+i]。
现给出a[1..n]和Q个询问(x,y),求与[x,y]匹配的区间的个数。
/*
写了n个小时,还没有调出来,Orz...
代码量倒是不大,但是细节巨多,已经弃疗了。。。 先差分一下, 然后题目就变成了,也就是这段区间取相反数之后可以与原区间匹配。
设当前询问为(x,y),把整个串取相反数,再复制到后面,用后缀数组向上向下二分出可行区间。
然后要求不可重叠,就是求rank在(l,r)中有多少串的位置在一个区间内,用主席树搞一搞。
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 200010
using namespace std;
int id[N],a[N],b[N],s[N],t1[N],t2[N],c[N],sa[N],rank[N],height[N],n;
int lg2[N],st[N][],sum[N*],son[N*][],root[N],cnt;
struct node{
int x,num;
bool operator<(const node&s1)const{
if(x==s1.x) return num<s1.num;
return x<s1.x;
}
}r[N];
bool cmp(int *y,int a,int b,int k){
int a1=y[a],b1=y[b];
int a2=a+k<=n?y[a+k]:-;
int b2=b+k<=n?y[b+k]:-;
return a1==b1&&a2==b2;
}
void DA(){
int *x=t1,*y=t2,m=;
for(int i=;i<=n;i++) r[i]=(node){s[i],i};
sort(r+,r+n+);
for(int i=;i<=n;i++) sa[i]=r[i].num;
x[sa[]]=;
for(int i=;i<=n;i++) x[sa[i]]=r[i].x==r[i-].x?m:++m;
for(int k=,p=;k<=n;k*=,m=p,p=){
for(int i=n-k+;i<=n;i++) y[++p]=i;
for(int i=;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k;
for(int i=;i<=m;i++) c[i]=;
for(int i=;i<=n;i++) c[x[y[i]]]++;
for(int i=;i<=m;i++) c[i]+=c[i-];
for(int i=n;i;i--) sa[c[x[y[i]]]--]=y[i];
swap(x,y);p=;x[sa[]]=;
for(int i=;i<=n;i++)
if(cmp(y,sa[i-],sa[i],k)) x[sa[i]]=p;
else x[sa[i]]=++p;
if(p>=n) break;
}
}
void geth(){
for(int i=;i<=n;i++) rank[sa[i]]=i;
for(int i=,j=;i<=n;i++){
if(rank[i]==) continue;
while(s[i+j]==s[sa[rank[i]-]+j]) j++;
height[rank[i]]=j;
if(j) j--;
}
for(int i=;i<=n;i++) lg2[i]=lg2[i>>]+;
for(int i=;i<=n;i++) st[i][]=height[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<=n;i++)
st[i][j]=min(st[i][j-],st[i+(<<j-)][j-]);
}
void insert(int &k,int last,int l,int r,int pos){
k=++cnt;
son[k][]=son[last][];
son[k][]=son[last][];
sum[k]=sum[last]+;
if(l==r) return;
int mid=l+r>>;
if(pos<=mid) insert(son[k][],son[last][],l,mid,pos);
else insert(son[k][],son[last][],mid+,r,pos);
}
int query(int k,int l,int r,int x,int y){
if(l>=x&&r<=y) return sum[k];
int mid=l+r>>,tot=;
if(x<=mid) tot+=query(son[k][],l,mid,x,y);
if(y>mid) tot+=query(son[k][],mid+,r,x,y);
return tot;
}
int querymn(int x,int y){
int k=lg2[y-x+];
return min(st[x][k],st[y-(<<k)+][k]);
}
int work(int x,int y){
int pos=rank[x],l=,r=pos,tmp1=pos,tmp2=pos;
while(l<r-){
int mid=l+r>>;
if(querymn(mid+,pos)>=y-x+) r=mid,tmp1=mid;
else l=mid;
}
l=pos,r=n+;
while(l<r-){
int mid=l+r>>;
if(querymn(pos+,mid)>=y-x+) l=mid,tmp2=mid;
else r=mid;
}
int ans1=query(root[tmp2],,n+,x+n/+,y+n/+)-query(root[tmp1-],,n+,x+n/+,y+n/+);
int ans2=query(root[tmp2],,n,,n/)-query(root[tmp1-],,n,,n/);
return tmp2-tmp1+-ans1-ans2;
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<n;i++) s[i]=a[i+]-a[i],s[i+n]=-s[i];s[n]=-1e9;
n=n*-;DA();geth();
for(int i=;i<=n;i++)
insert(root[i],root[i-],,n,sa[i]);
int Q;scanf("%d",&Q);
while(Q--){
int x,y;scanf("%d%d",&x,&y);
if(x==y){
printf("%d\n",n/);
continue;
}
printf("%d\n",work(x,y-));
}
return ;
}
Fence(codeforces 232D)的更多相关文章
- 【CF484E】Sign on Fence(主席树)
[CF484E]Sign on Fence(主席树) 题面 懒得贴CF了,你们自己都找得到 洛谷 题解 这不就是[TJOI&HEOI 排序]那题的套路吗... 二分一个答案,把大于答案的都变成 ...
- (CodeForces - 5C)Longest Regular Bracket Sequence(dp+栈)(最长连续括号模板)
(CodeForces - 5C)Longest Regular Bracket Sequence time limit per test:2 seconds memory limit per tes ...
- Painting The Fence(贪心+优先队列)
Painting The Fence(贪心+优先队列) 题目大意:给 m 种数字,一共 n 个,从前往后填,相同的数字最多 k 个在一起,输出构造方案,没有则输出"-1". 解题思 ...
- Sorted Adjacent Differences(CodeForces - 1339B)【思维+贪心】
B - Sorted Adjacent Differences(CodeForces - 1339B) 题目链接 算法 思维+贪心 时间复杂度O(nlogn) 1.这道题的题意主要就是让你对一个数组进 ...
- CF448C Painting Fence (分治递归)
Codeforces Round #256 (Div. 2) C C. Painting Fence time limit per test 1 second memory limit per tes ...
- (CodeForces 558C) CodeForces 558C
题目链接:http://codeforces.com/problemset/problem/558/C 题意:给出n个数,让你通过下面两种操作,把它们转换为同一个数.求最少的操作数. 1.ai = a ...
- SPOJ:House Fence(分治&DP)
"Holiday is coming, holiday is coming, hurray hurray!" shouts Joke in the last day of his ...
- [题解]Yet Another Subarray Problem-DP 、思维(codeforces 1197D)
题目链接:https://codeforces.com/problemset/problem/1197/D 题意: 给你一个序列,求一个子序列 a[l]~a[r] 使得该子序列的 sum(l,r)-k ...
- 【Codeforces】【图论】【数量】【哈密顿路径】Fake bullions (CodeForces - 804F)
题意 有n个黑帮(gang),每个黑帮有siz[i]个人,黑帮与黑帮之间有有向边,并形成了一个竞赛完全图(即去除方向后正好为一个无向完全图).在很多年前,有一些人参与了一次大型抢劫,参与抢劫的人都获得 ...
随机推荐
- XML字符串解析
不多说,直接上代码: import java.io.StringReader; import org.dom4j.Document; import org.dom4j.DocumentExceptio ...
- GNU汇编逻辑或算数左移右移
lsl 左移 .text .global _start _start: mov r1,#0b1 mov r1,r1,lsl#2 ROR循环右移 .text .global _start _star ...
- SQL Server中的日期,时间组合查询
如图所示,Jdate和Jdate2是两个分开的字段,一个是date类型,存储日期,一个是time(0)类型,存储具体时间 现在有这样的要求,就是获得(Jdate和Jdate2组合起来的日期时间)在(当 ...
- pandas知识点(处理缺失数据)
pandas使用浮点值NaN表示浮点和非浮点数组中的缺失数据: In [14]: string_data = Series(['aardvark','artichoke',np.nan,'avocad ...
- Essential C++ 3.1 节的代码练习——哨兵方式
#include "IncrementArray.hpp" template <typename element> element *find_address(elem ...
- DFS:Prime Ring Problem(素数环)
解体心得: 1.一个回溯法,可以参考八皇后问题. 2.题目要求按照字典序输出,其实在按照回溯法得到的答案是很正常的字典序.不用去特意排序. 3.输出有个坑,就是在输出一串的最后不能有空格,不然要PE, ...
- 7、python中的字典
字典是python内置的一种无序.可变的数据结构. 字典也叫哈希表.什么是哈希表?哈希表就是会对表中的键(key)执行哈希计算,并根据计算结果在内存中分配一个区域来储存该键所对应的值(value).这 ...
- Linux命令之---which简单介绍
命令简介 which命令的作用是,在PATH变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果.也就是说,使用which命令,就可以看到某个系统命令是否存在,以及执行的到底是哪一个位置的 ...
- 配置网络策略中的 NAP 条件
TechNet 库 Windows Server Windows Server 2008 R2 und Windows Server 2008 按类别提供的 Windows Server 内容 Win ...
- psql 工具详细使用介绍
psql 介绍 psql 是 PostgreSQL 中的一个命令行交互式客户端工具, 它允许你交互地键入 SQL 命令,然后把它们发送给 PostgreSQL 服务器,再显示 SQL 或命令的结果. ...