Codeforces232D. Fence

http://codeforces.com/problemset/problem/232/D

  给你一个长度为n 的序列A,有定两个值L1,S,求L2,满足:

    1.[L1,L1+s??1]和[L2,L2+s??1]不相交,均在[1,n]内。
    2.对于任意0<k<s,有Bk=A[L1+k]+A[L2+k],要求所有Bk相等。
  有Q 组询问,对于给定的L1和s,有多少L2 满足要求。

  看起来并不是字符串题,但是却可以转化啊囧。

  条件可以看成是这样的:

    对于0<i<s,A[l1+i]+A[l2+i]=A[l1+i-1]+A[l2+i-1]。

    移项,得到A[l1+i]-A[l1+i-1]=A[l2+i-1]-A[l2+i]。

  那不就可以看成这个数组的差分数组和差分数组中每一项取相反数得到的数组的长度为S的公共子串吗?(当然还有条件1的限制)

  对于每次询问,我们找到l1起始的后缀的排名,即rank[l1],向上向下二分出lcp(up,low)≥S的区间,然后相当于在这个区间中查询满足[sa[i],sa[i]+s-1]不与[l1,l1+s-1]相交的后缀的个数。用可持久化线段树查询即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100015;
vector<int> w;
int n,q,len,s[maxn],p[maxn<<1];
struct Tsegment{
    static const int maxn=::maxn<<1,maxk=20;
    int tot,L,R;
    struct Tnode{
        Tnode *c[2];int siz;
    }*root[maxn],T[maxn*maxk];
    void clear(int l,int r){
        L=l;R=r;tot=0;root[0]=T;root[0]->siz=0;
        root[0]->c[0]=root[0]->c[1]=root[0];
    }
    Tnode *newnode(Tnode *x){
        Tnode *cur=T+(++tot);
        *cur=*x;return cur;
    }
    void modify(Tnode *ever,Tnode *&now,int l,int r,int x){
        now=newnode(ever);++now->siz;
        int mid=(l+r)>>1;if (l==r) return;
        if (x<=mid) modify(ever->c[0],now->c[0],l,mid,x);
        else modify(ever->c[1],now->c[1],mid+1,r,x);
    }
    int query(Tnode *ever,Tnode *now,int l,int r,int a,int b){
        if (l==a&&r==b) return now->siz-ever->siz;
        if (a>b) return 0;int mid=(l+r)>>1;
        if (b<=mid) return query(ever->c[0],now->c[0],l,mid,a,b);
        else if (a>=mid+1) return query(ever->c[1],now->c[1],mid+1,r,a,b);
        else return query(ever->c[0],now->c[0],l,mid,a,mid)+query(ever->c[1],now->c[1],mid+1,r,mid+1,b);
    }
    void modify(int ever,int now,int x){modify(root[ever],root[now],L,R,x);}
    int query(int ever,int now,int a,int b){return query(root[ever],root[now],L,R,a,b);}
}segment;
struct Tsuffix_array{
    static const int maxn=::maxn<<1,maxk=20;
    int sum[maxn],sa[maxn],rank[maxn],tsa[maxn],trank[maxn];
    bool cmp(int i,int j,int l){
        if (i+l>len||j+l>len) return 0;
        return rank[i]==rank[j]&&rank[i+l]==rank[j+l];
    }
    void suffix_sort(int s[]){
        int m=len,p,i,j;
        for (i=0;i<=m;++i) sum[i]=0;
        for (i=1;i<=len;++i) ++sum[rank[i]=s[i]];
        for (i=1;i<=m;++i) sum[i]+=sum[i-1];
        for (i=len;i>=1;--i) sa[sum[rank[i]]--]=i;
        for (j=1,p=0;p<len;j<<=1,m=p){
            for (p=0,i=len-j+1;i<=len;++i) tsa[++p]=i;
            for (i=1;i<=len;++i) if (sa[i]>j) tsa[++p]=sa[i]-j;
            for (i=0;i<=m;++i) sum[i]=0;
            for (i=1;i<=len;++i) ++sum[rank[tsa[i]]];
            for (i=1;i<=m;++i) sum[i]+=sum[i-1];
            for (i=len;i>=1;--i) sa[sum[rank[tsa[i]]]--]=tsa[i];
            for (p=trank[sa[1]]=1,i=2;i<=len;++i) trank[sa[i]]=cmp(sa[i],sa[i-1],j)?p:++p;
            memcpy(rank,trank,sizeof(int)*(len+1));
        }
    }
    int height[maxn];
    void get_height(int s[]){
        for (int h=0,i=1;i<=len;++i){
            if (rank[i]==1) continue;
            for (h?--h:0;s[i+h]==s[sa[rank[i]-1]+h];++h);
            height[rank[i]]=h;
        }
    }
    int fmn[maxk][maxn];
    void prepare(){
        for (int i=1;i<=len;++i) fmn[0][i]=height[i];
        for (int k=1;k<maxk;++k)
            for (int i=1<<k;i<=len;++i)
                fmn[k][i]=min(fmn[k-1][i],fmn[k-1][i-(1<<(k-1))]);
        segment.clear(1,len);
        for (int i=1;i<=len;++i) segment.modify(i-1,i,sa[i]);
    }
    int lcp(int l,int r){
        if (++l>r) return len-sa[r]+1;
        int k=log2(r-l+1);
        return min(fmn[k][r],fmn[k][l+(1<<k)-1]);
    }
    int calc_up(int pos,int lim){
        int l=1,r=pos,res;
        while (l<=r){
            int mid=(l+r)>>1;
            lcp(mid,pos)>=lim?r=(res=mid)-1:l=mid+1;
        }
        return res;
    }
    int calc_low(int pos,int lim){
        int l=pos,r=len,res;
        while (l<=r){
            int mid=(l+r)>>1;
            lcp(pos,mid)>=lim?l=(res=mid)+1:r=mid-1;
        }
        return res;
    }
    int query(int l,int r){
        int length=r-l;
        int up=calc_up(rank[l],length),low=calc_low(rank[l],length);
        l+=n;r+=n;
        return segment.query(up-1,low,n+1,l-length-1)+segment.query(up-1,low,r+1,len);
    }
}SA;
void init(){
    scanf("%d",&n);len=(n<<1)-1;p[n]=2e9+1;
    for (int i=1;i<=n;++i) scanf("%d",&s[i]);
    for (int i=2;i<=n;++i){p[i-1]=s[i]-s[i-1];p[n+i-1]=s[i-1]-s[i];}
    for (int i=1;i<=len;++i) w.push_back(p[i]);
    sort(w.begin(),w.end());w.erase(unique(w.begin(),w.end()),w.end());
    for (int i=1;i<=len;++i) p[i]=lower_bound(w.begin(),w.end(),p[i])-w.begin()+1;
}
void work(){
    SA.suffix_sort(p);SA.get_height(p);
    SA.prepare();scanf("%d",&q);
    for (int l,r,i=1;i<=q;++i){
        scanf("%d%d",&l,&r);
        if (l==r) printf("%d\n",n-1);
        else printf("%d\n",SA.query(l,r));
    }
}
int main(){
    init();
    work();
    return 0;
}

my code

时间: 2024-10-20 00:29:05

Codeforces232D. Fence的相关文章

[POJ3253] Fence Repair

Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He then purchases a s

POJ1037:A decorative fence(DP)

Description Richard just finished building his new house. Now the only thing the house misses is a cute little wooden fence. He had no idea how to make a wooden fence, so he decided to order one. Somehow he got his hands on the ACME Fence Catalogue 2

USACO 4.1 Fence Loops(Floyd求最小环)

Fence Loops The fences that surround Farmer Brown's collection of pastures have gotten out of control. They are made up of straight segments from 1 through 200 feet long that join together only at their endpoints though sometimes more than two fences

洛谷P2738 [USACO4.1]篱笆回路Fence Loops

P2738 [USACO4.1]篱笆回路Fence Loops 11通过 21提交 题目提供者该用户不存在 标签USACO 难度提高+/省选- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 农夫布朗的牧场上的篱笆已经失去控制了.它们分成了1~200英尺长的线段.只有在线段的端点处才能连接两个线段,有时给定的一个端点上会有两个以上的篱笆.结果篱笆形成了一张网分割了布朗的牧场.布朗想将牧场恢复原样,出于这个考虑,他首先得知道牧场上哪一块区域的周长最小. 布朗将他的每段篱笆从1到N进行了标号

Fence(poj1821)

Fence Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4705   Accepted: 1489 Description A team of k (1 <= K <= 100) workers should paint a fence which contains N (1 <= N <= 16 000) planks numbered from 1 to N from left to right. E

HA高可用集群部署(ricci+luci+fence) 双机热备

主机环境 redhat6.5 6位 实验环境 服务端1 ip172.25.29.1   主机名:server1.example.com   ricci     服务端2 ip172.25.29.2    主机名:server2.example.com    ricci     管理端1 ip172.25.29.3    主机名:server3.example.com    luci     管理端2 ip172.25.29.250     fence_virtd 防火墙状态:关闭 1. 安装ri

poj 3253 Fence Repair

Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 40465   Accepted: 13229 Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000)

POJ 3253 Fence Repair (优先队列)

POJ 3253 Fence Repair (优先队列) Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needsN (1 ≤ N ≤ 20,000) planks of wood, each having some integer lengthLi (1 ≤ Li ≤ 50,000) units. He the

(困难) CF 484E Sign on Fence,整体二分+线段树

Bizon the Champion has recently finished painting his wood fence. The fence consists of a sequence of n panels of 1 meter width and of arbitrary height. The i-th panel's height is hi meters. The adjacent planks follow without a gap between them. Afte