UESTC 1059 秋实大哥与小朋友(线段树+离散化)

原题链接

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值