2016集训队论文吉如一

讲的都是一些自己不太想得到的题目

1.区间取min,区间查询最大值,区间求和

这个之前做过

记录区间最大值mx1,次大值mx2,最大值个数

插入的时候分情况讨论

if (mx1<x) 不做

if (max1>=x&&max2<x) 赋值max1

不然就递归下去

复杂度势能分析我没仔细学。。。

2.区间取min,区间加,区间求和

和上一题的区别在于有了区间加,延用上一题的处理办法就可以了

3.区间取min,区间取max,区间求和

变成维护6个标记

7.区间修改,区间赋值,查询区间最大值,查询历史区间最大值

如果没有区间赋值,我们可以增加一个历史lazy最大值这么一个标记

有了区间赋值我们发现这个并不能维护

但我们注意到一旦一个区间被区间赋值之后,对它进行区间加等同于区间赋值

于是我们对区间分类

9.

和7有点像

我们注意到把某个地方权值等同于修改[i,j](其中i<=x,j>=x)

区间赋值操作需要时间先后(就是先打哪个标记是有影响的)

所以这个东西不能用二维线段树来搞。。

但是kd-tree可以解决

(二维的除了线段树(同类的)和kd-tree还有其他东西么。。。)

kd-tree我们可以先把询问点离线弄出来

kd-tree处理高维问题相比线段树代码肯定是简单的

需要注意的就是 kd-tree还需要维护自己节点的信息

所以我们要记录 当前节点自己最小值 当前节点现在自己的值 当前lazy标记的值 lazy标记未下传的最小值

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rint register ll
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define mid ((h+t)>>1)
const ll N=2e5+10;
const ll INF=1e18;
ll n,m,cnt,rt,cmp_d;
ll a[N],sum[N];
struct re1{
  ll a,b,c;
}b[N];
struct re{
  ll d[2],v;
}p[N];
bool cmp(re x,re y)
{
  return(x.d[cmp_d]<y.d[cmp_d]);
}
#define umax(x,y) if (x<y) x=y
#define umin(x,y) if (x>y) x=y
struct kd{
  ll ls[N],rs[N],Mx[N],Nx[N],My[N],Ny[N],v[N];
  ll lazy[N],mlazy[N],nlazy[N],tlazy[N];
  IL void updata(ll x)
  {
    if (ls[x])
    {
      umax(Mx[x],Mx[ls[x]]);
      umax(My[x],My[ls[x]]);
      umin(Nx[x],Nx[ls[x]]);
      umin(Ny[x],Ny[ls[x]]); 
    }
    if (rs[x])
    {
      umax(Mx[x],Mx[rs[x]]);
      umax(My[x],My[rs[x]]);
      umin(Nx[x],Nx[rs[x]]);
      umin(Ny[x],Ny[rs[x]]);
    }
  }
  IL void down(ll x)
  {
    if (tlazy[x]<0)
    { 
      umin(tlazy[ls[x]],lazy[ls[x]]+tlazy[x]); 
      umin(tlazy[rs[x]],lazy[rs[x]]+tlazy[x]);
      umin(mlazy[ls[x]],nlazy[ls[x]]+tlazy[x]); 
      umin(mlazy[rs[x]],nlazy[rs[x]]+tlazy[x]);
    }
    nlazy[ls[x]]+=lazy[x]; nlazy[rs[x]]+=lazy[x];
    lazy[ls[x]]+=lazy[x]; lazy[rs[x]]+=lazy[x];
    lazy[x]=tlazy[x]=0;
  }
  ll build(rint h,rint t,rint o)
  {
    cmp_d=o; nth_element(p+h,p+mid,p+t+1,cmp);
    rint x=mid;
    Mx[x]=Nx[x]=p[x].d[0];
    My[x]=Ny[x]=p[x].d[1];
    v[x]=p[x].v;
    if (h!=x) ls[x]=build(h,mid-1,o^1); else ls[x]=0;
    if (t!=x) rs[x]=build(mid+1,t,o^1); else rs[x]=0;
    updata(x);
    return(x);
  }
  void change(ll x,ll hx,ll tx,ll hy,ll ty,ll k)
  {
    down(x);
    if (hx>Mx[x]||tx<Nx[x]||hy>My[x]||ty<Ny[x]) return;
    if (hx<=Nx[x]&&Mx[x]<=tx&&hy<=Ny[x]&&My[x]<=ty)
    {
      lazy[x]+=k; nlazy[x]+=k;
      if (k<0) tlazy[x]+=k;
      umin(mlazy[x],nlazy[x]); return;
    }
    if (hx<=p[x].d[0]&&p[x].d[0]<=tx&&hy<=p[x].d[1]&&p[x].d[1]<=ty)
    {
      nlazy[x]+=k; umin(mlazy[x],nlazy[x]);
    }
    if (ls[x]) change(ls[x],hx,tx,hy,ty,k);
    if (rs[x]) change(rs[x],hx,tx,hy,ty,k);
  }
  ll find(ll x,ll p1,ll p2)
  {
    if (!x) return(INF); 
    down(x);
    if (p1>Mx[x]||p1<Nx[x]||p2>My[x]||p2<Ny[x]) return(INF);
    if (p1==p[x].d[0]&&p2==p[x].d[1])
    {
      return mlazy[x]==INF?v[x]:v[x]+mlazy[x];
    }
    return(min(find(ls[x],p1,p2),find(rs[x],p1,p2)));
  }
}K;
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false);
  cin>>n>>m;
  rep(i,1,n) cin>>a[i],sum[i]=sum[i-1]+a[i];
  rep(i,1,m)
  {
    ll kk,x,y;
    cin>>kk>>x>>y;
    b[i].a=x,b[i].b=y,b[i].c=kk;
    if (kk==2)
    {
      p[++cnt].d[0]=x; p[cnt].d[1]=y; p[cnt].v=sum[y]-sum[x-1];
    }
  }
  if (cnt) rt=K.build(1,cnt,0);
  rep(i,1,m)
  {
    if (b[i].c==1)
    {
      K.change(rt,1,b[i].a,b[i].a,n,b[i].b-a[b[i].a]);
      a[b[i].a]=b[i].b;
    } else
    {
      cout<<K.find(rt,b[i].a,b[i].b)<<endl;
    }
  }
  return 0;
}
原文地址:https://www.cnblogs.com/yinwuxiao/p/9588675.html