原题链接
Problem Description
秋实大哥以周济天下,锄强扶弱为己任,他常对天长叹:安得广厦千万间,大庇天下寒士俱欢颜。
所以今天他又在给一群小朋友发糖吃。
他让所有的小朋友排成一行,从左到右标号。在接下去的时间中,他有时会给一段区间的小朋友每人v颗糖,有时会问第x个小朋友手里有几颗糖。
这对于没上过学的孩子来说实在太困难了,所以你看不下去了,请你帮助小朋友回答所有的询问。
Input
第一行包含两个整数n,m,表示小朋友的个数,以及接下来你要处理的操作数。
接下来的mm行,每一行表示下面两种操作之一:
0 l r v : 表示秋实大哥给[l,r]这个区间内的小朋友每人v颗糖
1 x : 表示秋实大哥想知道第x个小朋友手里现在有几颗糖
1≤m,v≤100000,1≤l≤r≤n,1≤x≤n,1≤n≤100000000。
Output
对于每一个1 x操作,输出一个整数,表示第x个小朋友手里现在的糖果数目。
Sample Input
3 4
0 1 3 1
1 2
0 2 3 3
1 3
Sample Output
1
4
解题思路
线段树区间修改,单点查询,但是n很大无法直接建树,由于操作数比较小,考虑对数据进行离散化处理。将整个区间分成子区间和端点,然后各自建立线段树维护大小。具体的方法是找到各个区间的左右端点然后推入vector然后排序,去重,在执行操作时通过索引,二分找到线段树上对应的点,剩下的就是普通的线段树操作了。
AC代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
#include<vector>
#include<string>
#include<queue>
#include<list>
#include<stack>
#include<set>
#include<map>
#define ll long long
#define ull unsigned long long
//#define rep(i,a,b) for (int i=(a),_ed=(b);i<_ed;i++)
#define rep(i,n) for(int i = 0;i < n; i++)
#define fil(a,b) memset((a),(b),sizeof(a))
#define cl(a) fil(a,0)
#define pb push_back
#define mp make_pair
#define ee 2.7182818
#define PI 3.141592653589793
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define eps 1e-7
#define mod 1000000007ll
using namespace std;
const int maxnode=5e6+20;
ll y11,y2;
int op=1;
ll v;
struct IntervalTree
{
ll sumv[maxnode];
ll addv[maxnode];
ll setv[maxnode];
void maintain(int o,int L,int R)
{
int lson=o<<1;
int rson=o<<1|1;
if(R>L)
{
sumv[o]=sumv[lson]+sumv[rson];
}
if(setv[o]>=0)
{
sumv[o]=setv[o]*(R-L+1);
}
if(addv[o])
{
sumv[o]+=addv[o]*(R-L+1);
}
}
void pushdown(int o)
{
int lson=o<<1;
int rson=o<<1|1;
if(setv[o]>=0)
{
setv[lson]=setv[rson]=setv[o];
addv[lson]=addv[rson]=0;
setv[o]=-1;
}
if(addv[o])
{
addv[lson]+=addv[o];
addv[rson]+=addv[o];
addv[o]=0;
}
}
void update(int o,int L,int R)
{
int lson=o<<1;
int rson=o<<1|1;
if(y11<=L&&y2>=R)
{
if(op==1)
{
addv[o]+=v;
}
else
{
setv[o]=v;
addv[o]=0;
}
}
else
{
pushdown(o);
int m=L+R>>1;
if(y11<=m) update(lson,L,m);
else maintain(lson,L,m);
if(y2>m) update(rson,m+1,R);
else maintain(rson,m+1,R);
}
maintain(o,L,R);
}
void query(int o,int L,int R,ll& ssum,ll& smin,ll& smax)
{
int lson=o<<1;
int rson=o<<1|1;
maintain(o,L,R);
if(y11<=L&&y2>=R)
{
ssum=sumv[o];
}
else
{
pushdown(o);
int m=L+R>>1;
ll lsum=0,lmin=inf,lmax=-inf;
ll rsum=0,rmin=inf,rmax=-inf;
if(y11<=m)
{
query(lson,L,m,lsum,lmin,lmax);
}
else maintain(lson,L,m);
if(y2>m)
{
query(rson,m+1,R,rsum,rmin,rmax);
}
else maintain(rson,m+1,R);
ssum=lsum+rsum;
}
}
}tr,t;
ll qqq[200010][5];
vector<ll> pt;
set<ll> st;
int main(void)
{
ll n,m;
ll tmp,l,r,x;
cin>>n>>m;
for(int z=1;z<=(int)(m);++z)
{
scanf("%lld",&qqq[z][0]);
if(qqq[z][0]==0)
{
scanf("%lld%lld%lld",&qqq[z][1],&qqq[z][2],&qqq[z][3]);
pt.pb(qqq[z][1]);
pt.pb(qqq[z][2]);
}
else scanf("%lld",&qqq[z][1]);
}
pt.pb(1);
pt.pb(100000000);
sort(pt.begin(),pt.end());
pt.erase(unique(pt.begin(), pt.end()), pt.end());
for(int i=0;i<pt.size();++i)
{
st.insert(pt[i]);
}
for(int z=1;z<=(int)(m);++z)
{
if(qqq[z][0]==0)
{
if(qqq[z][1]!=qqq[z][2])
{
y2=(ll)(lower_bound(pt.begin(), pt.end(),qqq[z][2])-pt.begin());
y11=(ll)(lower_bound(pt.begin(), pt.end(),qqq[z][1])-pt.begin()+1);
v=qqq[z][3];
t.update(1,1,pt.size()-1);
y2++;
tr.update(1,1,pt.size());
}
else
{
y11=y2=(ll)(lower_bound(pt.begin(), pt.end(),qqq[z][1])-pt.begin()+1);
v=qqq[z][3];
tr.update(1,1,pt.size());
}
}
else
{
if(st.find(qqq[z][1])!=st.end())
{
ll ssum=0,a,b;
ll pos=(ll)(lower_bound(pt.begin(), pt.end(),qqq[z][1])-pt.begin()+1);
y11=y2=pos;
tr.query(1,1,pt.size(),ssum,a,b);
printf("%lld\n",ssum);
}
else
{
ll ssum=0,a,b;
int pos=lower_bound(pt.begin(), pt.end(),qqq[z][1])-pt.begin();
y11=y2=(ll)pos;
t.query(1,1,pt.size()-1,ssum,a,b);
printf("%lld\n",ssum);
}
}
}
return 0;
}