每日一题 牛客基础 第六场 动态最小生成树 最小生成树 线段树
如题所示,这是一道大水题,因为写过的线段树实在是太少了,所以来水一篇
思路还是挺简单的。首先开一棵线段树记录电影的总和,问题是怎么去掉包含x的所有区间的值。那其实我只需要再开一棵线段树,每次遇到一个区间的时候,记录一下删去其中一个元素的时候需要减去的值,即是整个区间的长度乘以对这个区间的值。最后用第一棵线段数1到n的总和减去第二棵线段树x的值就是答案了。
上代码
#include<bits/stdc++.h>
#define int long long
#define MAXN 2000005
using namespace std;
struct node
{
int l,r,v,col;
} sgt[2][MAXN];
void iniSgt(int p,int l,int r)
{
sgt[0][p].l=l;
sgt[0][p].r=r;
sgt[1][p].l=l;
sgt[1][p].r=r;
if(l==r)
return;
int mid=(l+r)/2;
iniSgt(p*2,l,mid);
iniSgt(p*2+1,mid+1,r);
}
void down(int p,int o)
{
if(sgt[o][p].col)
{
int l=sgt[o][p].l,r=sgt[o][p].r;
int mid=(l+r)/2;
sgt[o][p*2].v+=sgt[o][p].col*(mid-l+1);
sgt[o][p*2+1].v+=sgt[o][p].col*(r-mid);
sgt[o][p*2].col+=sgt[o][p].col;
sgt[o][p*2+1].col+=sgt[o][p].col;
sgt[o][p].col=0;
}
}
void modify(int p,int o,int L,int R,int v)
{
int l=sgt[o][p].l,r=sgt[o][p].r;
if(l>=L&&r<=R)
{
sgt[o][p].col+=v;
sgt[o][p].v+=(r-l+1)*v;
return;
}
down(p,o);
int mid=(l+r)/2;
if(L<=mid)
modify(p*2,o,L,R,v);
if(R>=mid+1)
modify(p*2+1,o,L,R,v);
sgt[o][p].v=sgt[o][p*2].v+sgt[o][p*2+1].v;
}
int query(int p,int o,int x,int y)
{
int l=sgt[o][p].l,r=sgt[o][p].r;
if(x<=l&&y>=r)
return sgt[o][p].v;
down(p,o);
int mid=(l+r)/2,res=0;
if(x<=mid)
res+=query(p*2,o,x,y);
if(y>mid)
res+=query(p*2+1,o,x,y);
return res;
}
signed main()
{
int n,m;cin>>n>>m;
iniSgt(1,1,n);
for(int i=1;i<=m;i++)
{
int t;cin>>t;
if(t==0)
{
int l,r,z;cin>>l>>r>>z;
modify(1,0,l,r,z);
modify(1,1,l,r,(r-l+1)*z);
}
if(t==1)
{
int x;cin>>x;
cout<<query(1,0,1,n)-query(1,1,x,x)<<endl;
}
}
}
//244ms