8.13 杂题

P1471 方差

我们把方差公式展开:

img

所以只需要维护一个区间平方和和区间和

当我们更新一个区间加时

img

\(pushdown\) 易得

注意 \(double\) 的使用

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
const int N = 1e5 + 5;
// char buf[1<<24] , *p1 , *p2;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m;

double a[N];

struct Tree
{
	struct node { double sum , sqrsum , add; } t[N<<2];
	inl void pushadd ( int p , int l , int r , double val ) { t[p].add += val , t[p].sqrsum += 2 * t[p].sum * val + ( r - l + 1 ) * val * val , t[p].sum += ( r - l + 1 ) * val; }
	inl void down ( int p , int l , int r ) { if ( t[p].add ) pushadd ( lson , t[p].add ) , pushadd ( rson , t[p].add ) , t[p].add = 0; }
	inl void up ( int p ) { t[p].sum = t[ls].sum + t[rs].sum , t[p].sqrsum = t[ls].sqrsum + t[rs].sqrsum; }
	void build ( int p , int l , int r )
	{
		if ( l == r ) return t[p].sum = a[l] , t[p].sqrsum = a[l] * a[l] , void();
		build ( lson ) , build ( rson ) , up(p);
	}
	void upd ( int p , int l , int r , int x , int y , double val )
	{
		if ( x <= l && r <= y ) return pushadd ( p , l , r , val ) , void();
		down ( p , l , r );
		if ( x <= mid ) upd ( lson , x , y , val );
		if ( mid + 1 <= y ) upd ( rson , x , y , val );
		up(p);
	}
	double query1 ( int p , int l , int r , int x , int y )
	{	
		if ( x <= l && r <= y ) return t[p].sum;
		double res = 0; down ( p , l , r );
		if ( x <= mid ) res += query1 ( lson , x , y );
		if ( mid + 1 <= y ) res += query1 ( rson , x , y );
		return res;
	}
	double query2 ( int p , int l , int r , int x , int y )
	{
		if ( x <= l && r <= y ) return t[p].sqrsum;
		double res = 0; down ( p , l , r );
		if ( x <= mid ) res += query2 ( lson , x , y );
		if ( mid + 1 <= y ) res += query2 ( rson , x , y );
		return res;
	}
}T;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , m = read();
	for ( int i = 1 ; i <= n ; i ++ ) cin >> a[i];
	T.build ( 1 , 1 , n );
	for ( int i = 1 ; i <= m ; i ++ )
	{
		int op = read() , l = read() , r = read(); double w;
		if ( op == 1 ) cin >> w , T.upd ( 1 , 1 , n , l , r , w );
		if ( op == 2 ) cout << fixed << setprecision(4) << T.query1 ( 1 , 1 , n , l , r ) / ( 1.0 * ( r - l + 1 ) ) << endl;
		if ( op == 3 )
		{
			double temp1 = T.query1 ( 1 , 1 , n , l , r ) / ( 1.0 * ( r - l + 1 ) );
			double temp2 = T.query2 ( 1 , 1 , n , l , r ) / ( 1.0 * ( r - l + 1 ) );
			cout << fixed << setprecision(4) << temp2 - temp1 * temp1 << endl;
		}
	}
	return 0;
}

P5906 【模板】回滚莫队&不删除莫队

回滚莫队总是细节很多......

这题加点操作很好维护 但是删点操作很难维护 那么考虑使用回滚莫队

那么我们记录\(st[a[i]]\)数组和\(ed[a[i]]\)数组表示最早的\(a[i]\)的出现位置即可

对于滚动的左端点 单独记录\(tempst\)\(temped\)两个数组即可

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
const int N = 2e5 + 5;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
// #define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , a[N] , st[N] , ed[N] , cnt[N] , bel[N] , block , tot , ll[N] , rr[N] , tmp[N] , l , r , lstblock , ans[N] , res , tempst[N] , temped[N];

vector<int>lsh;

struct que { int l , r , id; } q[N];


signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);

	n = read();
	for ( int i = 1 ; i <= n ; i ++ ) a[i] = read() , lsh.eb(a[i]);
	sort ( lsh.begin() , lsh.end() );
	lsh.erase ( unique ( lsh.begin() , lsh.end() ) , lsh.end() );
	for ( int i = 1 ; i <= n ; i ++ ) a[i] = lower_bound ( lsh.begin() , lsh.end() , a[i] ) - lsh.begin();

	block = sqrt(n) , tot = n / block;
	if ( n % block ) tot ++;
	for ( int i = 1 ; i <= n ; i ++ ) bel[i] = ( i - 1 ) / block + 1;
	for ( int i = 1 ; i <= tot ; i ++ ) ll[i] = ( i - 1 ) * block + 1 , rr[i] = i * block; rr[tot] = n;

	m = read();
	for ( int i = 1 ; i <= m ; i ++ ) q[i].l = read() , q[i].r = read() , q[i].id = i;
	sort ( q + 1 , q + m + 1 , [](const que &a , const que &b) { return bel[a.l] == bel[b.l] ? a.r < b.r : bel[a.l] < bel[b.l]; } );
	l = 1 , r = 0;	
	for ( int i = 1 ; i <= m ; i ++ )
	{
		if ( bel[q[i].l] == bel[q[i].r] )
		{
			int temp = 0;
			for ( int j = q[i].l ; j <= q[i].r ; j ++ ) tmp[a[j]] = j;
			for ( int j = q[i].l ; j <= q[i].r ; j ++ ) temp = max ( temp , tmp[a[j]] - j );
			ans[q[i].id] = temp;
			for ( int j = q[i].l ; j <= q[i].r ; j ++ ) tmp[a[j]] = 0;
			continue;
		}
		if ( lstblock ^ bel[q[i].l] )
		{
			for ( int j = l ; j <= r ; j ++ ) st[a[j]] = ed[a[j]] = 0;
			l = rr[bel[q[i].l]] + 1 , r = rr[bel[q[i].l]];
			res = 0; lstblock = bel[q[i].l];
		}
		while ( r < q[i].r ) { ++ r; if ( !st[a[r]] ) st[a[r]] = r; ed[a[r]] = r , res = max ( res , ed[a[r]] - st[a[r]] ); }
		int temp = res , _l = l;
		while ( q[i].l < _l ) { -- _l; if ( !temped[a[_l]] ) temped[a[_l]] = _l; tempst[a[_l]] = _l , res = max ( res , max ( temped[a[_l]] , ed[a[_l]] ) - tempst[a[_l]] ); }
		ans[q[i].id] = res;
		while ( _l < l ) tempst[a[_l]] = temped[a[_l]] = 0 , ++_l;
		res = temp;
	}
	for ( int i = 1 ; i <= m ; i ++ ) cout << ans[i] << endl;
	return 0;
}

P4147 玉蟾宫

先预处理每一个点能向上延伸多远的距离

那么我们对于每一行维护一个单调递增的单调栈 栈中记录\(hei\)\(wei\)两个数表示这个块的宽度和高度

每次将高度大于等于当前高度的栈顶都弹出 每一次弹栈都统计答案 记录 \(temp\) 表示能扩展的最大宽度即可

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
const int N = 1e3 + 5;
// char buf[1<<24] , *p1 , *p2;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , pos[N][N] , ans;

struct que { int wei , hei; } sta[10000+5];

void solve ( int i )
{
	int top = 0 , temp = 0;
	sta[++top] = { 1 , pos[i][1] };
	for ( int j = 2 ; j <= m ; j ++ )
	{
		temp = 0;
		while ( sta[top].hei >= pos[i][j] && top )
		{
			temp += sta[top].wei;
			ans = max ( ans , sta[top--].hei * temp );
		}
		sta[++top] = { temp + 1 , pos[i][j] };
	}
	temp = 0;
	while ( top > 0 )
	{
		temp += sta[top].wei;
		ans = max ( ans , sta[top--].hei * temp );
	}
}

char ch;
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , m = read();
	for ( int i = 1 ; i <= n ; i ++ )
		for ( int j = 1 ; j <= m ; j ++ )
			cin >> ch , pos[i][j] = ( ch == 'F' ) ? pos[i-1][j] + 1 : 0;
	for ( int i = 1 ; i <= n ; i ++ ) solve ( i );
	cout << ans * 3 << endl;
	return 0;
}
posted @ 2023-08-14 10:43  Echo_Long  阅读(10)  评论(0编辑  收藏  举报