2024-1-12 DAY3

发布时间 2024-01-12 23:56:10作者: zfxyyy

2024-1-12 DAY3

D - Max GEQ Sum

经典线段树调几个小时

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;

const int N = 2e5 + 10;
int a[N];
int ll[N],rr[N];
int pre[N];
int n;

struct node
{
	int l,r;
	int Max;
	int Min;
}segTree[N*3];

void build(int i,int l,int r){
	segTree[i].l = l;
	segTree[i].r = r;
	segTree[i].Max = 0;
	if(l==r) return;
	int mid = l + r >> 1;
	build(i<<1,l,mid);
	build((i<<1)|1,mid+1,r);
}

//更新第k个值为val
void update(int i,int k,int val){
	if(segTree[i].l == k && segTree[i].r == k){
		segTree[i].Max = segTree[i].Min = val;
		return;
	}
	int mid = (segTree[i].l + segTree[i].r) >> 1;
	if(k <= mid) update(i<<1,k,val);
	else		 update((i<<1)|1,k,val);
	
	segTree[i].Max = max(segTree[i<<1].Max,segTree[(i<<1)|1].Max);
	segTree[i].Min = min(segTree[i<<1].Min,segTree[(i<<1)|1].Min);
}

pair<int,int> query(int i,int l,int r){
	if(segTree[i].l >= l &&segTree[i].r <= r)
		return {segTree[i].Min,segTree[i].Max};
	int mid = (segTree[i].l + segTree[i].r) >> 1;
	if(r<=mid) return query(i<<1,l,r);
	else if(l>mid) return query((i<<1)|1,l,r);
	else{
		auto [a1,b1] = query(i<<1,l,mid);
		auto [a2,b2] = query(i<<1|1,mid+1,r);
		return {min(a1,a2),max(b1,b2)}; 
	}
}

void solve()
{
 	cin >> n;
 	for(int i=1;i<=n;i++)
 	{
 		cin >> a[i];
 		pre[i] = pre[i-1] + a[i];
 	}
 	stack<int> path;
 	a[0] = 1e10;
 	a[n+1] = 1e10;
 	for(int i=1;i<=n+1;i++)
 	{
 		if(path.empty()) path.push(i);
 		else{
 			if(a[i]<=a[path.top()]) path.push(i);
 			else{
 				while(path.size()&&a[i]>a[path.top()])
 				{
 					int x=path.top();
 					rr[x] = i;
 					path.pop();
 				}
 				path.push(i);
 			}
 		}
 	}
 	while(path.size()) path.pop();
 	for(int i=n;i>=0;i--)
 	{
 		if(path.empty()) path.push(i);
 		else{
 			if(a[i]<=a[path.top()]) path.push(i);
 			else{
 				while(path.size()&&a[i]>a[path.top()])
 				{
 					int x=path.top();
 					ll[x] = i;
 					path.pop();
 				}
 				path.push(i);
 			}
 		}
 	}
 	
 	build(1,0,n);
 	for(int i=0;i<=n;i++) update(1,i,pre[i]);

 	for(int i=1;i<=n;i++)
 	{
 		auto [a1,b1] = query(1,ll[i],i-1);
 		auto [a2,b2] = query(1,i,rr[i]-1);
 		// cout << i <<endl;
 		// cout << ll[i] << " " << rr[i] <<endl;
 		if((pre[i-1]-a1>0) || (b2-pre[i]>0))
 		{
 			//cout << i <<endl;
 			cout << "NO" <<endl;
 			return;
 		}
 		// cout << i <<endl;
 		// cout << a1 << " " << b1 << endl;
 		// cout << a2 << " " << b2 << endl;
 		// cout << pre[i-1] << " " << pre[i] <<endl;
 	}
 	cout << "YES" <<endl;
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int T = 1;
	cin >> T;
	while(T--) solve();
    return 0;
}

C - Water the Trees

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;

const int N = 3e5 + 10;
int h[N];
int n;
int maxx = 0;
bool check(int time){
	int x = time / 2; //偶数
	int y = time - x; //奇数
	for(int i=1;i<=n;i++){
		int len = maxx - h[i];
		int z = min(len/2,x);
		x -= z;
		len -= 2*z;
		z = min(len,y);
		y -= z;
		len -=z;
		if(len!=0) return false;
	}
	return true;
}

void solve()
{
 	int r = 1e18;
 	int l = 0;
 	maxx = 0;
 	int ans = 1e18;
 	cin >> n;
 	for(int i=1;i<=n;i++)
 	{
 		cin >> h[i];
 		maxx = max(maxx,h[i]);
 	}
 	while(l<=r){
 		int mid = l + r >> 1;
 		if(check(mid)){
 			r = mid - 1;
 			ans = min(ans,mid);
 		}else l = mid + 1;
 	}
 	l = 0;
 	r = 1e18;
 	maxx++;
  	while(l<=r){
 		int mid = l + r >> 1;
 		if(check(mid)){
 			r = mid - 1;
 			ans = min(ans,mid);
 		}else l = mid + 1;
 	}
 	cout << ans <<endl;
}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int T = 1;
	cin >> T;
	while(T--) solve();
    return 0;
}

今天偷个懒