线段树 利用数组来维护一个类似前缀和的区间和 在查询的时候查这个区间数组 特殊操作 有延时标记 在区间数组上增加基本不改变原来数组 以达到节省时间的目的
树状数组 和线段树类似 一个用一个数组维护类似前缀和的东西 但 是 它维护的是一个用二进制表示的前缀和 举个例子 1是1、2是1 2、3是3、4是1 2 3 4、5是5、6 是5 6、7是7、8是1 2 3 4 5 6 7 8
划分数 用两个二位数组 来查找区间内第几大的数 第一个数组是存数的 另一个是用来存前i个有几个进入了左侧 还有 数组是对半分的 每次下一层都是上层区间对半分
LL tree0[1000000];
LL tree11[20][1000000];
LL tree12[20][1000000];
void build_tree(LL x,LL y,LL n)
{
if(x==y)
{
return ;
}
LL sum=y-x+1;
LL mid=(x+y)>>1;
LL max1=tree0[mid];
LL right=0,left=0;
for(i=x;i<=y;i++)
{
if(tree11[n][i]<max1)
sum--;
}
for(i=x;i<=y;i++)
{
if(x==i)
tree12[n][i]=0;
else
tree12[n][i]=tree12[n][i-1];
if(tree11[n][i]<max1||(tree11[n][i]==max1&&sum))
{
tree12[n][i]++;
tree11[n+1][x+(right++)]=tree11[n][i];
}
else
{
tree11[n+1][mid+(left++)]=tree11[n][i];
}
}
build_tree(x,mid,n+1);
build_tree(mid+1,n+1);
}
LL querty(LL x,LL y,LL qx,LL qy,LL k,LL n)
{
if(qx==qy)
return tree11[n][qx];
LL mid=(x+y)>>1;
LL left;
Ll qleft;
if(x==qx)
left=0;
else
left=tree12[n][qx-1];
qleft=tree12[n][qy]-left;
if(qleft>=k)
{
LL newx=x+left;
LL newy=newx+qleft-1;
querty(x,y,newx,newy,k,n+1);
}
else
{
LL newx=mid+qx-x+1-left;
LL newy=newx+qy-qx+1-qleft-1;
querty(mid+1,y,newx,newy,k-qleft,n+1);
}
}
线段树
#define length node[i].r-node[i].l+1
struct qwe{
ll r,l;
ll mid()
{
return (r+l)/2;
}
};
ll upup(ll i)
{
node[i].v=node[i<<1].v+node[i<<1|1].v;
}
ll build_tree(ll i,ll l,ll r)
{
node[i].r=r;
node[i].l=l;
if(node[i].r==node[i].l)
{
sum[i]=1;
add[i]=0;
return ;
}
ll m=node[i].mid();
build_tree(i<<1,l,m);
build_tree(i<<1|1,m+1,r);
upup(i);
}
ll updown(ll i,ll lenth)
{
if(add[i])
{
add[i<<1]+=add[i];
add[i<<1|1]+=add[i];
sum[i<<1]+=add[i]*(lenth-(lenth>>1));
sum[i<<1|1]+=add[i]*(lenth>>1);
add[i]=0;
}
}
ll update(ll l,ll r,ll i,ll v)
{
if(l==node[i].l&&node[i].r)
{
sum[i]+=v*(r-l+1);
add[i]+=v;
}
updown(i,length);
ll mid=node[i].mid();
if(r<=mid)
{
update(l,r,i<<1,v);
}
else
{
if(l>mid)
{
update(l,r,i<<1|1,v);
}
else
{
update(l,mid,i<<1,v);
update(mid+1,r,i<<1|1,v);
}
}
}
ll querty(ll i,ll l,ll r)
{
if(l==node[i].l&&node[i].r)
{
m+=sum[i];
}
updown(i,length);
//两种书写方式都行
i=i<<1;
if(node[i].r>=l)
{
if(node[i].r>=r)
{
querty(i,l,r);
}
else
querty(i,l,node[i].r);
}
i++;
if(node[i].l<=r)
{
if(l>=node[i].l)
{
querty(i<<1|1,l,r);
}
else
querty(i<<1,node[i].l,r);
}
//第二种
ll mid=node[i].mid();
if(mid>=r)
{
querty(i<<1,l,r);
}
else
{
if(mid<l)
querty(i<<1|1,l,r);
else
{
querty(i<<1,l,mid);
querty(i<<1|1,mid+1,r);
}
}
}
ll lowbit(ll i)
{
return i&(-i);
}
ll update(ll i,ll a)
{
while(i<=n)
{
c[i]+=a;
i+=lowbit(i);
}
}
ll getsum(ll i)
{
ll sum=0;
while(i>0)
{
sum+=c[i];
i-=lowbit(i);
}
return sum;
}