#193. 字符串查询

来源:互联网 发布:linux命令解压缩 编辑:程序博客网 时间:2024/06/08 11:24

听说有个经典题叫二维偏序统计,即求坐标平面上给定矩形内的点数。
可以通过二位前缀和转化为求一个点左下角的点数。
再换个角度,求一个数列中每个数之前小于它的数的个数,可以用树状数组轻松处理。
同样的,可以将平面上的点与矩形的端点排序,当枚举到前者就执行add操作,枚举到后者就执行query操作。
然后这题就可做了。考虑串按前缀、后缀分别排序后,相同前缀、后缀的串都是一段区间,然后就转化为上述的二维数点,就能把这题A掉了。

#include<cstdio>#include<iostream>#include<algorithm>#include<string>#include<cstdlib>#include<cmath>using namespace std;#define rep(i,j,k) for(i=j;i<=k;++i)#define per(i,j,k) for(i=j;i>=k;--i)#define ll long long#define db double#define ldb long double#define pii pair<int,int>#define mkp make_pair#define X first#define Y secondconst int N=50005;int n,Q,sa1[N],sa2[N],rk1[N],rk2[N],cnt,sum[N][4],c[N];string s1[N],s2[N],a,b;pii qj[N][4];struct TMP{pii p,wz;}tmp[N*5];bool cmp1(int x,int y){return s1[x]<s1[y];}bool cmp2(int x,int y){return s2[x]<s2[y];}bool cmp(TMP x,TMP y){return x.p==y.p?x.wz<y.wz:x.p<y.p;}void add(int x){    for(;x<=n;x+=x&-x)++c[x];}int query(int x){    int z=0;    for(;x;x-=x&-x)z+=c[x];    return z;}int main(){    int i,j,l,la,ra,lb,rb;    cin>>n>>Q;    rep(i,1,n){        cin>>s1[i];l=s1[i].size();        per(j,l-1,0)s2[i]+=s1[i][j];        sa1[i]=sa2[i]=i;    }    sort(sa1+1,sa1+n+1,cmp1);sort(sa2+1,sa2+n+1,cmp2);    rep(i,1,n)rk1[sa1[i]]=i,rk2[sa2[i]]=i;    rep(i,1,n)tmp[++cnt]=(TMP){mkp(rk1[i],rk2[i]),mkp(-1,-1)};    sort(s1+1,s1+n+1);sort(s2+1,s2+n+1);    s1[n+1]=s2[n+1]="{";    rep(i,1,Q){        cin>>a>>b;l=b.size();        rep(j,0,l-j-1)swap(b[j],b[l-j-1]);        la=lower_bound(s1+1,s1+n+1,a)-s1-1;        a+='{';ra=lower_bound(s1+1,s1+n+1,a)-s1-1;        lb=lower_bound(s2+1,s2+n+1,b)-s2-1;        b+='{';rb=lower_bound(s2+1,s2+n+1,b)-s2-1;        tmp[++cnt]=(TMP){qj[i][0]=mkp(ra,rb),mkp(i,0)};        tmp[++cnt]=(TMP){qj[i][1]=mkp(ra,lb),mkp(i,1)};        tmp[++cnt]=(TMP){qj[i][2]=mkp(la,rb),mkp(i,2)};        tmp[++cnt]=(TMP){qj[i][3]=mkp(la,lb),mkp(i,3)};    }    sort(tmp+1,tmp+cnt+1,cmp);    rep(i,1,cnt){        if(tmp[i].wz.X==-1&&tmp[i].wz.Y==-1)add(tmp[i].p.Y);        else sum[tmp[i].wz.X][tmp[i].wz.Y]=query(tmp[i].p.Y);    }   rep(i,1,Q)printf("%d\n",sum[i][0]-sum[i][1]-sum[i][2]+sum[i][3]);    return 0;}
0 0
原创粉丝点击