1. 程式人生 > 其它 >P4041 [AHOI2014/JSOI2014]奇怪的計算器

P4041 [AHOI2014/JSOI2014]奇怪的計算器

一個 \(O(n\log^2 n)\) 的神奇做法。

這道題和那個 P4588 數學計算很像,所以能想到把所有數儲存起來做操作。

先想想上下界。我們珂以先排序,線段樹維護 Min,Max,再二分要修改的位置,二分出來後區間賦值。珂以用線段樹。(這裡我的區間賦值是先乘 \(0\) 再加值)

這樣 \(O(n\log^2n)\) 的複雜度:

inline void erfen1(){
	int le=1,ri=q;
	while(le<=ri){
		int Mid=le+ri>>1;
		if(query2(1,1,q,1,Mid)<=L)le=Mid+1;
		else ri=Mid-1;
	}
    if(le>=2){
	    modify2(1,1,q,1,le-1,0);
	    modify1(1,1,q,1,le-1,L);
    } 
}
inline void erfen2(){
	int le=1,ri=q;
	while(le<=ri){
		int Mid=le+ri>>1;
		if(query3(1,1,q,Mid,q)>=R)ri=Mid-1;
		else le=Mid+1;
	}
    if(ri<=q-1){
	    modify2(1,1,q,ri+1,q,0);
	    modify1(1,1,q,ri+1,q,R); 
    }
}

第一、二、三個加法、減法、乘法操作也可以線段樹。

第四個珂以想到用另一棵線段樹處理一下原數列區間最小、大值,再打標記。

但其實不需要。

因為排過序,而乘法的數字都大於零,所以相對位置不會改變。

所以我們珂以直接取左/右端點。

就是這樣:


inline void GAN(int k,int l,int r,int v){
	xds2[k]+=a[r].x*v;
	xds3[k]+=a[l].x*v;
	gan[k]+=v;
}

最後,吸口氧就可以快樂地跑過去了。

#include<bits/stdc++.h>
using namespace std;//add mul gan min max sum
#define int long long
const int maxn=1e5+5;
int xds2[maxn<<2]/*最大*/,xds3[maxn<<2]/*最小*/,add[maxn<<2],mul[maxn<<2],gan[maxn<<2],ans[maxn];
int op[maxn],num[maxn],n,L,R,q;//gan是操作4
struct nice{
    int x,id;
    bool operator <(const nice &b)const{return x<b.x;}
}a[maxn];
#define ls (k<<1)
#define rs (k<<1|1)
#define mid (l+r>>1)
inline void pushup(int k){
	xds2[k]=max(xds2[ls],xds2[rs]);
	xds3[k]=min(xds3[ls],xds3[rs]);
}
inline void GAN(int k,int l,int r,int v){
	xds2[k]+=a[r].x*v;
	xds3[k]+=a[l].x*v;
	gan[k]+=v;
}
inline void ADD(int k,int l,int r,int v){
	xds2[k]+=v,xds3[k]+=v;
	add[k]+=v;
}
inline void MUL(int k,int l,int r,int v){
	xds2[k]*=v,xds3[k]*=v,add[k]*=v,mul[k]*=v;gan[k]*=v;
}
void build(int k,int l,int r){
	mul[k]=1;
	if(l==r){
		xds2[k]=xds3[k]=a[l].x;
		return ;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(k); 
}
inline void pushdown(int k,int l,int r){
    if(mul[k]!=1){
    	MUL(ls,l,mid,mul[k]);
	    MUL(rs,mid+1,r,mul[k]);
	    mul[k]=1;
    }
    if(add[k]!=0){
    	ADD(ls,l,mid,add[k]);
    	ADD(rs,mid+1,r,add[k]);
    	add[k]=0;
    }
    if(gan[k]!=0){
    	GAN(ls,l,mid,gan[k]);
    	GAN(rs,mid+1,r,gan[k]);
    	gan[k]=0;
    }
}
void modify1(int k,int l,int r,int x,int y,int v){
	if(x<=l&&r<=y)return ADD(k,l,r,v);
	pushdown(k,l,r);
	if(x<=mid)modify1(ls,l,mid,x,y,v);
	if(mid<y)modify1(rs,mid+1,r,x,y,v);
	pushup(k);
}
void modify2(int k,int l,int r,int x,int y,int v){
	if(x<=l&&r<=y)return MUL(k,l,r,v);
	pushdown(k,l,r);
	if(x<=mid)modify2(ls,l,mid,x,y,v);
	if(mid<y)modify2(rs,mid+1,r,x,y,v);
	pushup(k);
}
void modify3(int k,int l,int r,int x,int y,int v){
	if(x<=l&&r<=y)return GAN(k,l,r,v);
	pushdown(k,l,r);
	if(x<=mid)modify3(ls,l,mid,x,y,v);
	if(mid<y)modify3(rs,mid+1,r,x,y,v);
	pushup(k);
}
int query(int k,int l,int r,int x){
	if(l==r)return xds2[k];
    pushdown(k,l,r);
	if(x<=mid)return query(ls,l,mid,x);
	else return query(rs,mid+1,r,x);
}
int query2(int k,int l,int r,int x,int y){
	if(x<=l&&r<=y)return xds2[k];
	pushdown(k,l,r);
	int res=-0x3f3f3f3f3f3f3f3f;
	if(x<=mid)res=max(res,query2(ls,l,mid,x,y));
	if(mid<y)res=max(res,query2(rs,mid+1,r,x,y));
	return res;
}
int query3(int k,int l,int r,int x,int y){
	if(x<=l&&r<=y)return xds3[k];
	pushdown(k,l,r);
	int res=0x3f3f3f3f3f3f3f3f;
	if(x<=mid)res=min(res,query3(ls,l,mid,x,y));
	if(mid<y)res=min(res,query3(rs,mid+1,r,x,y));
	return res;
}
inline void erfen1(){
	int le=1,ri=q;
	while(le<=ri){
		int Mid=le+ri>>1;
		if(query2(1,1,q,1,Mid)<=L)le=Mid+1;
		else ri=Mid-1;
	}
    if(le>=2){
	    modify2(1,1,q,1,le-1,0);
	    modify1(1,1,q,1,le-1,L);
    } 
}
inline void erfen2(){
	int le=1,ri=q;
	while(le<=ri){
		int Mid=le+ri>>1;
		if(query3(1,1,q,Mid,q)>=R)ri=Mid-1;
		else le=Mid+1;
	}
    if(ri<=q-1){
	    modify2(1,1,q,ri+1,q,0);
	    modify1(1,1,q,ri+1,q,R); 
    }
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
	cin>>n>>L>>R;
	for(int i=1;i<=n;i++){
		char c;
		cin>>c>>num[i];
		if(c=='+'){
			op[i]=1;
		}
		if(c=='-'){
			op[i]=1,num[i]=-num[i];
		}
		if(c=='*'){
			op[i]=2;
		}
		if(c=='@'){
			op[i]=3;
		}
	}
	cin>>q;
	for(int i=1;i<=q;i++)cin>>a[i].x,a[i].id=i;
	sort(a+1,a+q+1);
    build(1,1,q);
	for(int i=1;i<=n;i++){
		if(op[i]==1)ADD(1,1,q,num[i]);
		if(op[i]==2)MUL(1,1,q,num[i]);
		if(op[i]==3)GAN(1,1,q,num[i]);
		erfen1();
		erfen2();
	}
    for(int i=1;i<=q;i++)ans[a[i].id]=query(1,1,q,i);
    for(int i=1;i<=q;i++)cout<<ans[i]<<endl;
	return 0;
} 
YJX AK IOI