树状数组用法

1.结合kmp,维护顺序对和逆序对

(字符串)

const int N=10000+20,M=500000+50;
int txt[M],mod[M],ans[M],tot,t[N],equ[N],les[N],nxt[M];
int lt,lm,s;
inline int lowbit(int x)
{
return x&(-x);
}
inline void add(int x,int da)
{
while(x<=s)
{
t[x]+=da;
x+=lowbit(x);
}
}
inline int ask(int x)
{
int yu=0;
while(x)
{
yu+=t[x];
// chu("nowyu:%d\n",yu);
x-=lowbit(x);
}
return yu;
}
int main()
{
// freopen("exam.txt","r",stdin);
lt=re(),lm=re(),s=re();
_f(i,1,lt)txt[i]=re();
_f(i,1,lm)mod[i]=re(),add(mod[i],1),equ[i]=ask(mod[i]),les[i]=ask(mod[i]-1);
memset(t,0,sizeof(t));
int j=0;
_f(i,2,lm)
{
add(mod[i],1);
while(j&&(equ[j+1]!=ask(mod[i])||les[j+1]!=ask(mod[i]-1)))
{
_f(k,i-j,i-nxt[j]-1)add(mod[k],-1);
j=nxt[j];
}
if(equ[j+1]==ask(mod[i])&&les[j+1]==ask(mod[i]-1))++j;
nxt[i]=j;
//chu("to mod:nxt[%d]:%d\n",i,)
}

memset(t,0,sizeof(t));
j=0;
_f(i,1,lt)
{
add(txt[i],1);
while(j&&(equ[j+1]!=ask(txt[i])||les[j+1]!=ask(txt[i]-1)))
{
_f(k,i-j,i-nxt[j]-1)add(txt[k],-1);
j=nxt[j];

}
j++;
if(j==lm)
{
ans[++tot]=i-j+1;
_f(k,i-j+1,i-nxt[j])add(txt[k],-1);
j=nxt[j];
}
}
chu("%d\n",tot);
_f(i,1,tot)
chu("%d\n",ans[i]);

return 0;
}

posted on 2022-03-12 14:23  HZOI-曹蓉  阅读(25)  评论(0)    收藏  举报