CF1924B Space Harbour 题解
挺典的题。
考虑添加一个海港的贡献。用 set
维护目前的全部海港,显然只有在这个点前驱后继这一段区间会被修改。
注意到修改总是区间加等差数列。询问是区间和。线段树维护差分即可。复杂度
#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;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】