bzoj4262: Sum

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4262

思路:写这题之前推荐先写uoj164

类似做法的还有HNOI2016序列(我拿莫队水过了)

也是维护一个函数性质标记

题解见:http://www.cnblogs.com/clrs97/p/4824806.html


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn=100010,mod=(int)1e9,maxt=maxn<<2,inf=2147483647;
using namespace std;
int n,cnt,Q,stk[maxn],top;ll ans[maxn],a[maxn];
struct quer{int x,l,r,id,op;}q[maxn];
bool operator <(quer a,quer b){return a.x<b.x;}
struct data{
	ll a,b,c,d;
	void clear(){a=1,b=c=d=0;}
};
data operator +(data f,data g){
	return (data){
		f.a*g.a,     f.b*g.a+g.b,
		f.a*g.c+f.c, f.b*g.c+f.d+g.d
	};
}


void read(int &x){
    char ch;bool ok=0;
    for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    if (ok) x=-x;
}

struct Tsegment{
	#define ls (p<<1)
	#define rs (p<<1|1)
	#define mid ((l+r)>>1)
	ll len[maxt],v[maxt],s[maxt];data tag[maxt];
	void update(int p){v[p]=v[ls]+v[rs],s[p]=s[ls]+s[rs];}
	void addtag(int p,data t){
		s[p]=t.c*v[p]+t.d*len[p]+s[p];
		v[p]=t.a*v[p]+t.b*len[p];
		tag[p]=tag[p]+t;
	}
	void down(int p){addtag(ls,tag[p]),addtag(rs,tag[p]),tag[p].clear();}
	void build(int p,int l,int r){
		//printf("%d %d %d\n",p,l,r);
		tag[p].clear(),len[p]=r-l+1,v[p]=s[p]=0;
		if (l==r) return;
		build(ls,l,mid),build(rs,mid+1,r);
	}
	void modify(int p,int l,int r,int a,int b,data v){
		//printf("modify=%d %d %d %d %d\n",p,l,r,a,b);
		if (l==a&&r==b){addtag(p,v);return;}
		down(p);
		if (b<=mid) modify(ls,l,mid,a,b,v);
		else if (a>mid) modify(rs,mid+1,r,a,b,v);
		else modify(ls,l,mid,a,mid,v),modify(rs,mid+1,r,mid+1,b,v);
		update(p);
	}
	void cover(int l,int r,ll v){modify(1,1,n,l,r,(data){0,v,0,0}),addtag(1,(data){1,0,1,0});}
	ll query(int p,int l,int r,int a,int b){
		//printf("query=%d %d %d %d %d\n",p,l,r,a,b);
		if (l==a&&r==b) return s[p];
		down(p);
		if (b<=mid) return query(ls,l,mid,a,b);
		else if (a>mid) return query(rs,mid+1,r,a,b);
		else return query(ls,l,mid,a,mid)+query(rs,mid+1,r,mid+1,b);
	}
	ll query(int l,int r){return query(1,1,n,l,r);}
}T;

void work(ll op){
	T.build(1,1,n),a[0]=inf*op,stk[top=1]=0;
	//printf("cnt=%d\n",cnt);
	for (int i=1,j=1;i<=n;i++){
		while (top&&a[stk[top]]*op<=a[i]*op) top--;
		T.cover(stk[top]+1,i,a[i]);stk[++top]=i;
		for (;q[j].x<i;) j++;
		for (;q[j].x==i;j++){
			ans[q[j].id]+=op*T.query(q[j].l,q[j].r)*q[j].op;
			//printf("%lld\n",T.query(q[j].l,q[j].r));
			//printf("end=%d stl=%d str=%d\n",q[j].x,q[j].l,q[j].r);
		}
	}
}

int main(){
	scanf("%d",&Q);
	for (int i=1,l1,l2,r1,r2;i<=Q;i++){
		read(l1),read(r1),read(l2),read(r2),n=max(max(r1,n),r2);
		q[++cnt]=(quer){r2,l1,r1,i,1},q[++cnt]=(quer){l2-1,l1,r1,i,-1};
	}
	sort(q+1,q+1+cnt);
	//for (int i=1;i<=cnt;i++) printf("q=x=%d l=%d r=%d\n",q[i].x,q[i].l,q[i].r);
	//printf("%d\n",n);
	for (int i=1,t1=1023,t2=1025;i<=n;i++,t1=1ll*t1*1023%mod,t2=1ll*t2*1025%mod) a[i]=t1^t2;
	//for (int i=1;i<=n;i++) printf("%lld\n",a[i]);
	work(1),work(-1); 
	for (int i=1;i<=Q;i++) printf("%lld\n",ans[i]);
	return 0;
}

你可能感兴趣的:(bzoj4262: Sum)