CF1924B Space Harbour 题解

挺典的题。

考虑添加一个海港的贡献。用 set 维护目前的全部海港,显然只有在这个点前驱后继这一段区间会被修改。

注意到修改总是区间加等差数列。询问是区间和。线段树维护差分即可。复杂度 O(nlogn)O(n \log n)

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

const int N = 5e5 + 5, MOD = 1e9 + 7, HSMOD = 1610612741, HSMOD2 = 998244353; // Remember to change

int n, m, q, t, a[N];

namespace FastIo
{
	#define QUICKCIN ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
	int read()
	{
		char ch = getchar();
		int x = 0, f = 1;
		while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
		while (ch == '-')
		{
			f = -f;
			ch = getchar();
		}
		while (ch >= '0' && ch <= '9')
		{
			x = (x << 1) + (x << 3) + (ch ^ 48);
			ch = getchar();
		}
		return x * f;
	}
	template<class T>
	void write(T x)
	{
		if (x < 0)
		{
			putchar('-');
			x = -x;
		}
		if (x > 9) write(x / 10);
		putchar(x % 10 + '0');
	}
	template<class T>
	void writeln(T x)
	{
		write(x);
		putchar('\n');
	}
}

template<typename T>
class Bit
{
public:
	T lowbit(T x)
	{
		return x & -x;
	}
	T tr[N];
	void add(T x, T y)
	{
		while (x < N)
		{
			tr[x] += y;
			x += lowbit(x);
		}
	}
	T query(T x)
	{
		T sum = 0;
		while (x)
		{
			sum += tr[x];
			x -= lowbit(x);
		}
		return sum;
	}
};

int res[N];

int dcsl(int sx, int mx, int gc)
{
	int xs = (mx - sx) / gc + 1;
	return (sx + mx) * xs / 2ll;
}

class SegmentTree
{
public:
	struct Node
	{
		int l, r, sum, tag, tsum;
		friend Node operator+(const Node& x, const Node& y)
		{
			if(x.l==-1) return y;
			if(y.l==-1) return x;
			Node z;
			z.l=x.l,z.r=y.r;
			z.tag=0;
			z.sum=x.sum+y.sum;
			z.tsum=x.tsum+y.tsum+x.sum*(y.r-y.l+1);
			return z;
		}
	}tr[N << 2];
	void pushup(int u)
	{
		tr[u]=tr[u<<1]+tr[u<<1|1];
	}
	void pushtag(int u,int v)
	{
		tr[u].tag+=v;
		tr[u].sum+=(tr[u].r-tr[u].l+1)*v;
		tr[u].tsum+=v*dcsl(1,tr[u].r-tr[u].l+1,1);
	}
	void pushdown(int u)
	{
		if(tr[u].tag)
		{
			pushtag(u<<1,tr[u].tag);
			pushtag(u<<1|1,tr[u].tag);
			tr[u].tag=0;
		}
	}
	void build(int u, int l, int r, int *a)
	{
		tr[u]={l,r,a[l],0ll,a[l]};
		if(l==r) return;
		int mid=l+r>>1;
		build(u<<1,l,mid,a);
		build(u<<1|1,mid+1,r,a);
		pushup(u);
	}
	void update(int u, int l, int r, int c)
	{
		if(l>r) return;
		if(l>n||r>n||l<1||r<1) return;
		if(tr[u].l>=l and tr[u].r<=r)
		{
			pushtag(u,c);
			return;
		}
		pushdown(u);
		int mid=tr[u].l+tr[u].r>>1;
		if(l<=mid) update(u<<1,l,r,c);
		if(r>mid) update(u<<1|1,l,r,c);
		pushup(u); 
	}
	Node query(int u, int l, int r)
	{
		if(tr[u].l>=l and tr[u].r<=r) return tr[u];
		pushdown(u);
		int mid=tr[u].l+tr[u].r>>1;
		Node res;
		res.l=-1;
		if(l<=mid) res=query(u<<1,l,r);
		if(r>mid) res=res+query(u<<1|1,l,r);
		return res;
	}
}sgt;

set<pair<int, int>> st;
int loc[N], val[N];
bool v[N];
int cf[N];

signed main()
{
	ios::sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr);
	cin>>n>>m>>q;
	for(int i=1;i<=m;i++)
	{
		cin>>loc[i];
		v[loc[i]]=1;
	}
	for(int i=1;i<=m;i++) cin>>val[i],st.insert(make_pair(loc[i],val[i]));
	for(int i=1;i<=n;i++)
	{
		if(v[i])
		{
			res[i]=0ll;
			continue;
		}
		auto it=st.lower_bound(make_pair(i,(int)-1e18));
		auto i2=it;
		--i2;
		res[i]=(*i2).second*((*it).first-i);
	}
	for(int i=1;i<=n;i++) 
	{
		cf[i]=res[i]-res[i-1];
	}
	sgt.build(1,1,n,cf);
	while(q--)
	{
		int op;
		cin>>op;
		if(op==1)
		{
			int x, v;
			cin>>x>>v;
			auto it=st.lower_bound(make_pair(x,(int)-1e18));
			auto i2=it;
			--i2;
			int l=(*i2).first,r=(*it).first;
			sgt.update(1,l+1,r,(*i2).second);
			sgt.update(1,l+1,l+1,-(*i2).second*(r-l));
			// up ok
			sgt.update(1,l+1,x,-(*i2).second);
			sgt.update(1,l+1,l+1,(x-l)*(((*i2).second)));
			sgt.update(1,x+1,r,-v);
			sgt.update(1,x+1,x+1,(r-(x+1)+1)*v); 
			st.insert(make_pair(x,v));
		}
		else
		{
			int l,r;
			cin>>l>>r;
			cout<<(sgt.query(1,1,r).tsum)-(l==1?0ll:sgt.query(1,1,l-1).tsum)<<"\n";
		}
	}
	return 0;
}
posted @   HappyBobb  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示