ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

21.5.31 t1

2021-06-25 09:32:15  阅读:155  来源: 互联网

标签:21.5 ch int max 31 t1 inline void define


tag:线段树,贪心


根据贪心不难想到,每个物品都从大到小排序,然后一个区间的答案就是3个值的区间max乘起来。

所以要求的就是

\[\sum_{l\le r}max_a[l,r]\cdot max_b[l,r]\cdot max_c[l,r] \]

一个常见的套路,枚举右端点,线段树维护答案,用一个单调栈维护max的变化。

维护的时候要支持区间覆盖a/b/c,所以把 \(\sum a,b,c,ab,bc,ca,abc\) 全部记下来即可。

大常数 \(O(nlogn)\),\(2e5\) 本地 \(1.1s\)


#include<bits/stdc++.h>
using namespace std;

template<typename T>
inline void Read(T &n){
	char ch; bool flag=false;
	while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
	for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
	if(flag)n=-n;
}

enum{
	MAXN = 200005,
	MOD = 1000000007
};

inline int ksm(int base, int k=MOD-2){
	int res=1;
	while(k){
		if(k&1)
			res = 1ll*res*base%MOD;
		base = 1ll*base*base%MOD;
		k >>= 1;
	}
	return res;
}

inline int dec(int a, int b){
	// assert(0<=a and a<MOD and 0<=b and b<MOD);
	a -= b;
	if(a<0) a += MOD;
	return a;
}

inline int inc(int a, int b){
	// assert(0<=a and a<MOD and 0<=b and b<MOD);
	a += b;
	if(a>=MOD) a -= MOD;
	return a;
}

inline void ddec(int &a, int b){a = dec(a,b);}
inline void iinc(int &a, int b){a = inc(a,b);}
inline void upd(int &a, long long b){a = (a+b)%MOD;}

int n;
int a[3][MAXN], q[3][MAXN], top[3], ans;

struct node{
	int s1, s2, s3, s12, s23, s13, s123, fil1, fil2, fil3, sz;
	#define s1(x) t[x].s1
	#define s2(x) t[x].s2
	#define s3(x) t[x].s3
	#define s12(x) t[x].s12
	#define s23(x) t[x].s23
	#define s13(x) t[x].s13
	#define s123(x) t[x].s123
	#define fil1(x) t[x].fil1
	#define fil2(x) t[x].fil2
	#define fil3(x) t[x].fil3
	#define sz(x) t[x].sz
}t[MAXN<<2];

inline int lc(int x){return x<<1;}
inline int rc(int x){return x<<1|1;}

inline void Push_Up(int x){
	s1(x) = inc(s1(lc(x)),s1(rc(x)));
	s2(x) = inc(s2(lc(x)),s2(rc(x)));
	s3(x) = inc(s3(lc(x)),s3(rc(x)));
	s12(x) = inc(s12(lc(x)),s12(rc(x)));
	s23(x) = inc(s23(lc(x)),s23(rc(x)));
	s13(x) = inc(s13(lc(x)),s13(rc(x)));
	s123(x) = inc(s123(lc(x)),s123(rc(x)));
}

inline void Fill1(int x, int fil1){
	fil1(x) = fil1; 
	s1(x) = 1ll*sz(x)*fil1%MOD;
	s12(x) = 1ll*s2(x)*fil1%MOD;
	s13(x) = 1ll*s3(x)*fil1%MOD;
	s123(x) = 1ll*s23(x)*fil1%MOD;
}

inline void Fill2(int x, int fil2){
	fil2(x) = fil2;
	s2(x) = 1ll*sz(x)*fil2%MOD;
	s12(x) = 1ll*s1(x)*fil2%MOD;
	s23(x) = 1ll*s3(x)*fil2%MOD;
	s123(x) = 1ll*s13(x)*fil2%MOD;
}

inline void Fill3(int x, int fil3){
	fil3(x) = fil3;
	s3(x) = 1ll*sz(x)*fil3%MOD;
	s13(x) = 1ll*s1(x)*fil3%MOD;
	s23(x) = 1ll*s2(x)*fil3%MOD;
	s123(x) = 1ll*s12(x)*fil3%MOD;
}

inline void Push_Down(int x){
	if(~fil1(x))
		Fill1(lc(x),fil1(x)),
		Fill1(rc(x),fil1(x)),
		fil1(x) = -1;
	if(~fil2(x))
		Fill2(lc(x),fil2(x)),
		Fill2(rc(x),fil2(x)),
		fil2(x) = -1;
	if(~fil3(x))
		Fill3(lc(x),fil3(x)),
		Fill3(rc(x),fil3(x)),
		fil3(x) = -1;
}

void Build(int x, int head, int tail){
	sz(x) = tail-head+1;
	fil1(x) = fil2(x) = fil3(x) = -1;
	if(head==tail) return;
	int mid = head+tail >> 1;
	Build(lc(x),head,mid); Build(rc(x),mid+1,tail);
}

void Fill1(int x, int head, int tail, int l, int r, int fil1){
	if(l<=head and tail<=r) return Fill1(x,fil1);
	Push_Down(x);
	int mid = head+tail >> 1;
	if(l<=mid) Fill1(lc(x),head,mid,l,r,fil1);
	if(mid<r) Fill1(rc(x),mid+1,tail,l,r,fil1);
	Push_Up(x);
}

void Fill2(int x, int head, int tail, int l, int r, int fil2){
	if(l<=head and tail<=r) return Fill2(x,fil2);
	Push_Down(x);
	int mid = head+tail >> 1;
	if(l<=mid) Fill2(lc(x),head,mid,l,r,fil2);
	if(mid<r) Fill2(rc(x),mid+1,tail,l,r,fil2);
	Push_Up(x);
}

void Fill3(int x, int head, int tail, int l, int r, int fil3){
	if(l<=head and tail<=r) return Fill3(x,fil3);
	Push_Down(x);
	int mid = head+tail >> 1;
	if(l<=mid) Fill3(lc(x),head,mid,l,r,fil3);
	if(mid<r) Fill3(rc(x),mid+1,tail,l,r,fil3);
	Push_Up(x);
}

void check(int x=1, int head=1, int tail=n){
	if(head==tail){printf("%d %d %d\n",s1(x),s2(x),s3(x));return;}
	Push_Down(x);
	int mid = head+tail >> 1;
	check(lc(x),head,mid); check(rc(x),mid+1,tail);
}

inline int tp(int id){return q[id][top[id]];}

int main(){
	// freopen("1.in","r",stdin);
	// freopen("11.out","w",stdout);
	Read(n); Build(1,1,n);
	for(int i=1; i<=n; i++){
		for(int j=0; j<3; j++) Read(a[j][i]);
		for(int j=0; j<3; j++) for(int k=j+1; k<3; k++) if(a[j][i]<a[k][i]) swap(a[j][i],a[k][i]);
	}
	// for(int i=1; i<=n; i++,puts("")) for(int j=0; j<3; j++) printf("%d ",a[j][i]);puts("");
	for(int i=1; i<=n; i++){
		for(int j=0; j<3; j++)
			while(top[j] and a[j][tp(j)]<a[j][i]) top[j]--;
		Fill1(1,1,n,tp(0)+1,i,a[0][i]);
		Fill2(1,1,n,tp(1)+1,i,a[1][i]);
		Fill3(1,1,n,tp(2)+1,i,a[2][i]);
		for(int j=0; j<3; j++) q[j][++top[j]] = i;
		iinc(ans,s123(1));
		// check();puts("");
	}
	cout<<1ll*ksm(1ll*n*(n+1)/2%MOD)*ans%MOD<<'\n';
	return 0;
}

标签:21.5,ch,int,max,31,t1,inline,void,define
来源: https://www.cnblogs.com/oisdoaiu/p/14929472.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有