我的错误的想法是:使用树状数组维护一个数组pyz,这个数组表示,当我想访问现在的x的时候,我访问的是初始数组的x+pyz[x]。这可以使用树状数组维护,在每次删去现在位于x的元素时,令x~n的pyz都+1.剩下的部分就和题解一样使用线段树维护,只不过所有操作的x、y都要加上pyz[x]、pyz[y]。
但是这样做只有10pts。我想知道是为什么?
这是我的代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e6+10;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll n,m;
ll b[N];
struct tree
{
ll max,min;
}a[N*4];
#define mid ((lp+rp)>>1)
#define ls (p*2)
#define rs (p*2+1)
void update(ll p)
{
a[p].max=max(a[ls].max,a[rs].max);
a[p].min=min(a[ls].min,a[rs].min);
}
void build(ll p,ll lp,ll rp)
{
if(lp==rp)
{
a[p].max=a[p].min=b[lp];
return;
}
build(ls,lp,mid);
build(rs,mid+1,rp);
update(p);
}
void change(ll p,ll lp,ll rp,ll k)
{
if(lp==rp)
{
a[p].max=-inf;
a[p].min=inf;
return;
}
if(k<=mid)
change(ls,lp,mid,k);
else
change(rs,mid+1,rp,k);
update(p);
}
void chto(pair<ll,ll> &res,pair<ll,ll> to)
{
res.first=max(res.first,to.first);
res.second=min(res.second,to.second);
}
pair<ll,ll> query(ll p,ll lp,ll rp,ll l,ll r)
{
if(lp>=l && rp<=r)
{
return make_pair(a[p].max,a[p].min);
}
pair<ll,ll> res=make_pair(-inf,inf);
if(l<=mid)
chto(res,query(ls,lp,mid,l,r));
if(r>mid)
chto(res,query(rs,mid+1,rp,l,r));
return res;
}
ll t[N];
inline ll lowbit(const ll &x)
{
return x&-x;
}
void add(ll p,ll x)
{
for(ll i=p;i<=n;i+=lowbit(i))
t[i]+=x;
}
ll ask(ll p)
{
ll res=0;
for(ll i=p;i;i-=lowbit(i))
res+=t[i];
return res;
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
for(ll i=1;i<=n;i++)
cin>>b[i];
build(1,1,n);
for(ll i=1;i<=m;i++)
{
ll op,x,y;
cin>>op;
if(op==1)
{
cin>>x;
change(1,1,n,x+ask(x));
add(x,1);
}
else
{
cin>>x>>y;
x+=ask(x);
y+=ask(y);
//cout<<"Q:"<<x<<" "<<y<<endl;
pair<ll,ll> ans=query(1,1,n,x,y);
cout<<ans.second<<" "<<ans.first<<endl;
}
}
return 0;
}