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]个人,黑帮与黑帮之间有有向边,并形成了一个竞赛完全图(即去除方向后正好为一个无向完全图).在很多年前,有一些人参与了一次大型抢劫,参与抢劫的人都获得 ...
随机推荐
- 对比传统方式访问数据库和SpringData访问数据库
我们在写代码的时候应该一边写一边测试,这样的话可以尽快的找到错误,在代码写多了之后去找错误的话不容易给错误定位 传统方式访问数据库 1:创建一个Maven web项目 2:修改pom.xml为以下内容 ...
- (转)为什么在 2013 十月番中出现了很多以 3D 渲染代替传统 2D 绘画来表现人物的镜头?
一直都有的,特别是三次元这家公司一直致力于3d的风格化渲染既大家说的3d转2d.目前最厉害的商业化软件是pencil+,占领大部分的作品.而mentalray,早期用于disney的部分风格化渲染:i ...
- git初次建立远程仓库问题
git "Could not read from remote repository.Please make sure you have the correct access rights. ...
- Codeforces Round #461 (Div. 2) A. Cloning Toys
A. Cloning Toys time limit per test 1 second memory limit per test 256 megabytes Problem Description ...
- [Noip2016]换教室(期望+DP)
Description 题目链接:Luogu Solution 这题结合了DP和概率与期望,其实只要稍微知道什么是期望就可以了, 状态的构造很关键,\(F[i][j][0/1]\)表示已经到第\(i\ ...
- #include "*.c"文件的妙用
在看uCOS II V2.91版本源代码时,在ucos_ii.c源文件中发现下面的代码: #include <os_core.c> #include <os_flag.c> # ...
- Redis实现之字典跳跃表
跳跃表 跳跃表是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.跳跃表支持平均O(logN).最坏O(N)的时间复杂度查找,还可以通过顺序性操作来批量处理节 ...
- cglib动态代理之原理说明
cglib采用了非常底层的字节码技术,通过目标类的字节码,为目标类创建子类,并在子类中用方法拦截技术,拦截所有父类方法的调用,并对拦截方法进行增强. 1)底层采用字节码框架ASM,来转换字节码来生成新 ...
- laravel5.2总结--文件上传
1 配置 文件系统的配置文件在 config/filesystems.php 文件中,此处我们新建一个uploads本地磁盘空间用于存储上传的文件,具体配置项及说明如下: <?php retur ...
- 一道题目关于Java类加载
public class B { public static B t1 = new B(); public static B t2 = new B(); { System.out.println(&q ...