Codechef:The Street/STREETTA

传送门

题解:
第一个操作用李超树维护一下就行了。 时间复杂度 O ( m log ⁡ 2 n ) O(m \log^2 n) O(mlog2n)

#include 
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const LL inf=2e18;
const int N=3e5+50, L=1e9, T=60;

int n,m,rt,lc[N*T],rc[N*T],tot;
LL s1[N*T],d1[N*T]; // tag1
LL s2[N*T],d2[N*T]; // tag2
inline int newnode() {
	++tot;
	s1[tot]=-inf; d1[tot]=0;
	return tot;
}
inline LL calc(LL s,LL d,int p) {return s+d*p;}
inline void addtag1(int &k,int l,int r,LL s,LL d) {
	if(!k) {k=newnode(); s1[k]=s; d1[k]=d; return;}
	if(calc(s1[k],d1[k],l)<=calc(s,d,l)) swap(s1[k],s), swap(d1[k],d);
	if(l==r) return;
	int mid=(l+r)>>1;
	if(calc(s1[k],d1[k],mid)<=calc(s,d,mid)) {
		addtag1(lc[k],l,mid,s1[k],d1[k]);
		s1[k]=s; d1[k]=d;
	} else addtag1(rc[k],mid+1,r,s,d);
}
inline void addtag2(int k,int l,int r,LL s,LL d) {s2[k]+=s; d2[k]+=d;}
inline void add1(int &k,int l,int r,int L,int R,LL s,LL d) {
	if(!k) k=newnode();
	if(L<=l && r<=R) {addtag1(k,l,r,s,d); return;}
	int mid=(l+r)>>1;
	if(R<=mid) add1(lc[k],l,mid,L,R,s,d);
	else if(L>mid) add1(rc[k],mid+1,r,L,R,s,d);
	else add1(lc[k],l,mid,L,R,s,d), add1(rc[k],mid+1,r,L,R,s,d);
}
inline void add2(int &k,int l,int r,int L,int R,LL s,LL d) {
	if(!k) k=newnode();
	if(L<=l && r<=R) {addtag2(k,l,r,s,d); return;}
	int mid=(l+r)>>1;
	if(R<=mid) add2(lc[k],l,mid,L,R,s,d);
	else if(L>mid) add2(rc[k],mid+1,r,L,R,s,d);
	else add2(lc[k],l,mid,L,R,s,d), add2(rc[k],mid+1,r,L,R,s,d);
}
inline LL ask1(int k,int l,int r,int p) {
	if(!k) return -inf;
	LL val=calc(s1[k],d1[k],p);
	if(l==r) return val;
	int mid=(l+r)>>1;
	if(p<=mid) return max(val,ask1(lc[k],l,mid,p));
	else return max(val,ask1(rc[k],mid+1,r,p));
}
inline LL ask2(int k,int l,int r,int p) {
	if(!k) return 0;
	LL val=s2[k]+d2[k]*p;
	if(l==r) return val;
	int mid=(l+r)>>1;
	if(p<=mid) return val+ask2(lc[k],l,mid,p);
	else return val+ask2(rc[k],mid+1,r,p);
}
int main() {
	n=rd(), m=rd();
	for(int i=1;i<=m;i++) {
		int op=rd();
		if(op==1) {
			int l=rd(), r=rd(), a=rd(), b=rd();
			add1(rt,1,n,l,r,b-(LL)l*a,a);
		} else if(op==2) {
			int l=rd(), r=rd(), a=rd(), b=rd();
			add2(rt,1,n,l,r,b-(LL)l*a,a);
		} else {
			int pos=rd();
			LL val1=ask1(rt,1,n,pos);
			if(val1==-inf) {puts("NA"); continue;}
			LL val2=ask2(rt,1,n,pos);
			printf("%lld\n",val1+val2);
		}
	}
}

你可能感兴趣的:(线段树)