如题,这么写 push_down 函数是错的,WA 38分。
void push_down(ll u){
if(tr[u].mul!=1){
if(tr[u].l){tr[tr[u].l].mul=-tr[tr[u].l].mul;tr[tr[u].l].ad=-tr[tr[u].l].ad;tr[tr[u].l].val=-tr[tr[u].l].val;}
if(tr[u].r){tr[tr[u].r].mul=-tr[tr[u].r].mul;tr[tr[u].r].ad=-tr[tr[u].r].ad;tr[tr[u].r].val=-tr[tr[u].r].val;}
tr[u].mul=1;
// swap(tr[u].l, tr[u].r);
}
if(tr[u].ad!=0){
if(tr[u].l){tr[tr[u].l].ad+=tr[u].ad;tr[tr[u].l].val+=tr[u].ad;}
if(tr[u].r){tr[tr[u].r].ad+=tr[u].ad;tr[tr[u].r].val+=tr[u].ad;}
tr[u].ad=0;
}
if(tr[u].l&&tr[tr[u].l].val>tr[u].val||tr[u].r&&tr[tr[u].r].val<tr[u].val){
swap(tr[u].l, tr[u].r);
}
}
但是这么写是正确的,AC100分
void push_down(ll u){
if(tr[u].mul!=1){
if(tr[u].l){tr[tr[u].l].mul=-tr[tr[u].l].mul;tr[tr[u].l].ad=-tr[tr[u].l].ad;tr[tr[u].l].val=-tr[tr[u].l].val;}
if(tr[u].r){tr[tr[u].r].mul=-tr[tr[u].r].mul;tr[tr[u].r].ad=-tr[tr[u].r].ad;tr[tr[u].r].val=-tr[tr[u].r].val;}
tr[u].mul=1;
swap(tr[u].l, tr[u].r);
}
if(tr[u].ad!=0){
if(tr[u].l){tr[tr[u].l].ad+=tr[u].ad;tr[tr[u].l].val+=tr[u].ad;}
if(tr[u].r){tr[tr[u].r].ad+=tr[u].ad;tr[tr[u].r].val+=tr[u].ad;}
tr[u].ad=0;
}
// if(tr[u].l&&tr[tr[u].l].val>tr[u].val||tr[u].r&&tr[tr[u].r].val<tr[u].val){
// swap(tr[u].l, tr[u].r);
// }
}
这两个 push_down 唯一的区别在与什么时候交换儿子。正确的写法是在区间被翻转时交换左右儿子,错误的写法是在二叉查找树的性质不满足时交换左右儿子,为什么这么写就错了呢?
附:完整正确代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define rrep(i,a,b) for(ll i=(a);i>=(b);i--)
const ll N=2e5+9;
ll n, q;
ll a[N];
vector <pair<ll, ll> > ad[N], jian[N];
mt19937_64 myrand(0);
namespace fast_IO{//快读模板
#define FASTIO
#define IOSIZE 100000
char ibuf[IOSIZE],obuf[IOSIZE];char*p1=ibuf,*p2=ibuf,*p3=obuf;
#ifdef ONLINE_JUDGE
#define getchar()((p1==p2)and(p2=(p1=ibuf)+fread(ibuf,1,IOSIZE,stdin),p1==p2)?(EOF):(*p1++))
#define putchar(x)((p3==obuf+IOSIZE)&&(fwrite(obuf,p3-obuf,1,stdout),p3=obuf),*p3++=x)
#endif
#define isdigit(ch)(ch>47&&ch<58)
#define isspace(ch)(ch<33)
template<typename T>inline T read(){T s=0;int w=1;char ch;while(ch=getchar(),!isdigit(ch)and(ch!=EOF))if(ch=='-')w=-1;if(ch==EOF)return false;while(isdigit(ch))s=s*10+ch-48,ch=getchar();return s*w;}template<typename T>inline bool read(T&s){s=0;int w=1;char ch;while(ch=getchar(),!isdigit(ch)and(ch!=EOF))if(ch=='-')w=-1;if(ch==EOF)return false;while(isdigit(ch))s=s*10+ch-48,ch=getchar();return s*=w,true;}inline bool read(char&s){while(s=getchar(),isspace(s));return true;}inline bool read(char*s){char ch;while(ch=getchar(),isspace(ch));if(ch==EOF)return false;while(!isspace(ch))*s++=ch,ch=getchar();*s='\000';return true;}template<typename T>inline void print(T x){if(x<0)putchar('-'),x=-x;if(x>9)print(x/10);putchar(x%10+48);}inline void print(char x){putchar(x);}inline void print(char*x){while(*x)putchar(*x++);}inline void print(const char*x){for(int i=0;x[i];i++)putchar(x[i]);}
#ifdef _GLIBCXX_STRING
inline bool read(std::string&s){s="";char ch;while(ch=getchar(),isspace(ch));if(ch==EOF)return false;while(!isspace(ch))s+=ch,ch=getchar();return true;}inline void print(std::string x){for(int i=0,n=x.size();i<n;i++)putchar(x[i]);}
#endif
template<typename T,typename...T1>inline int read(T&a,T1&...other){return read(a)+read(other...);}template<typename T,typename...T1>inline void print(T a,T1...other){print(a);print(other...);}struct Fast_IO{~Fast_IO(){fwrite(obuf,p3-obuf,1,stdout);}}io;template<typename T>Fast_IO&operator>>(Fast_IO&io,T&b){return read(b),io;}template<typename T>Fast_IO&operator<<(Fast_IO&io,T b){return print(b),io;}
}using namespace fast_IO;
ll bcj[N];
ll findl(ll u){
if(bcj[u]==u)return u;
return bcj[u]=findl(bcj[u]);
}
struct treap{
// ll pos[N];//代表标记为i的点现在在tr数组中的下标
struct point{
ll val, key, l, r, fa, mul, ad;//id是标记, 先乘再加,val是真实值
}tr[N*32];
ll rt;
ll nN;
void push_down(ll u){
if(tr[u].mul!=1){
if(tr[u].l){tr[tr[u].l].mul=-tr[tr[u].l].mul;tr[tr[u].l].ad=-tr[tr[u].l].ad;tr[tr[u].l].val=-tr[tr[u].l].val;}
if(tr[u].r){tr[tr[u].r].mul=-tr[tr[u].r].mul;tr[tr[u].r].ad=-tr[tr[u].r].ad;tr[tr[u].r].val=-tr[tr[u].r].val;}
tr[u].mul=1;
swap(tr[u].l, tr[u].r);
}
if(tr[u].ad!=0){
if(tr[u].l){tr[tr[u].l].ad+=tr[u].ad;tr[tr[u].l].val+=tr[u].ad;}
if(tr[u].r){tr[tr[u].r].ad+=tr[u].ad;tr[tr[u].r].val+=tr[u].ad;}
tr[u].ad=0;
}
// if(tr[u].l&&tr[tr[u].l].val>tr[u].val||tr[u].r&&tr[tr[u].r].val<tr[u].val){
// swap(tr[u].l, tr[u].r);
// }
}
void split(ll u, ll v, ll &x, ll &y, ll xfa=0, ll yfa=0){
if(u==0){x=y=0;return;}
push_down(u);
if(tr[u].val<=v){
tr[u].fa=xfa;
x=u;
split(tr[u].r, v, tr[u].r, y, u, yfa);
}else{
tr[u].fa=yfa;
y=u;
split(tr[u].l, v, x, tr[u].l, xfa, u);
}
}
ll merge(ll u, ll v){
if(u==0||v==0)return u+v;
push_down(u);push_down(v);
if(tr[u].key>tr[v].key){
tr[u].r=merge(tr[u].r, v);
tr[tr[u].r].fa=u;
return u;
}else{
tr[v].l=merge(u, tr[v].l);
tr[tr[v].l].fa=v;
return v;
}
}
void insert(ll id, ll val){
ll curu=id;
tr[curu]=(point){val, myrand(), 0, 0, 0, 1, 0};
ll x=0, y=0;
split(rt, val, x, y);
rt=merge(merge(x, curu), y);
}
void dfs(ll u, ll other){
if(u==0)return;
bcj[findl(u)]=findl(other);
dfs(tr[u].l, other);
dfs(tr[u].r, other);
}
ll mergeWithIntersection(ll u, ll v){
if(u==0||v==0)return u+v;
push_down(u);push_down(v);
if(tr[u].key<tr[v].key){swap(u, v);}
ll x=0, y=0, z=0;
split(v, tr[u].val-1, x, y);
split(y, tr[u].val, y, z);
dfs(y, u);
// split(v, tr[u].val, x, z);
tr[u].l=mergeWithIntersection(tr[u].l, x);
tr[u].r=mergeWithIntersection(tr[u].r, z);
if(tr[u].l)tr[tr[u].l].fa=u;
if(tr[u].r)tr[tr[u].r].fa=u;
return u;
}
void replace(ll a){
ll x=0, y=0;
split(rt, (a>>1), x, y);
tr[x].mul*=-1;tr[x].ad*=-1;tr[x].val*=-1;
tr[x].ad+=a;tr[x].val+=a;
rt=mergeWithIntersection(x, y);
}
ll findwithID(ll id){
ll u=findl(id);
ll val=tr[u].val;
u=tr[u].fa;
while(u){
if(tr[u].mul==-1)val=-val;
val+=tr[u].ad;
u=tr[u].fa;
}
return val;
}
void print(ll u){
push_down(u);
// cout << tr[u].fa << ' ' << tr[u].val << ' ' << tr[u].id << ' ' << tr[u].mul << ' ' << tr[u].ad << ' ' << tr[u].l << ' ' << tr[u].r << " ; ";
if(tr[u].l&&tr[tr[u].l].val>tr[u].val)cout << "wrong " << endl;
if(tr[u].r&&tr[tr[u].r].val<tr[u].val)cout << "wrong " << endl;
if(tr[u].l)print(tr[u].l);
if(tr[u].r)print(tr[u].r);
}
}tree;
ll ans[N];
int main(){
// freopen("produce.out", "r", stdin);
// freopen("lyl.out", "w", stdout);
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
io >> n >> q;
rep(i, 1, q)bcj[i]=i;
rep(i, 1, n) io >> a[i];
rep(i, 1, q){
ll x, l, r;io >> x >> l >> r;
ad[l].emplace_back(make_pair(x, i));
jian[r+1].emplace_back(make_pair(x, i));
}
rep(i, 1, n+1){
for(auto v:ad[i]){
tree.insert(v.second, v.first);
}
for(auto v:jian[i]){
ans[v.second]=tree.findwithID(v.second);
}
tree.replace(a[i]);
}
rep(i, 1, q)io << ans[i] << '\n';
// cerr << "Time used: " << clock()*1.0/CLOCKS_PER_SEC << "s" << endl;
return 0;
}