• 线段树【p4879】ycz的妹子


    Description

    机房神犇yczycz有n个青梅竹马,她们分别住在1~n号城市中。小时候的她们美丽可爱,但是由于女大十八变,有些妹子的颜值发生了变化,但是十分重感情的(ycz)神犇不忍心抛弃她们,于是记录下来了她们颜值变化的值,我们用(C\, x\, y)表示第(x)个城市的妹子的颜值下降了(y)。长大之后的(ycz)非常有魅力,有许多妹子被(ycz)迷得神魂颠倒,我们用(I\, x\, y)表示第(x)个城市有一个妹子喜欢上了(ycz),她的颜值为(y)(y)有可能是负数,但是(ycz)来者不拒)。但在中途有一些妹子和(ycz)吵架了,于是就分手了,我们用(D\, x)表示(x)个妹子(ycz)分手了。

    最近神犇(ycz)要去全国各地找他的妹子们,为了方便计算,我们珂以把(ycz)的妹子所在的城市当作是一条直线,并且挨在一起。神犇(ycz)由于忙于和他的妹子们联系此时已经很累了,于是交给你一个这样的任务:他想知道他在某个时间去找他的所有妹子们珂以获得多大的愉悦度,这个愉悦度为他找的妹子的颜值数,你要做的就是求出这个愉悦度之和(注意长大后妹子们的颜值可能为负数/滑稽)。

    注意:每个城市只允许有一个妹子,也就是说后来喜欢上(ycz)的妹子会赶走之前这个城市喜欢(ycz)的妹子(一城不容二女)

    UPD:

    青梅竹马都是喜欢(ycz)的。

    分手的第(x)个妹子不是第(x)城市的妹子,是指从前往后数第(x)个有妹子的城市的妹子

    青梅竹马长大后就是妹子

    修改的值(y)不为负数,但是颜值减去之后可能为负数

    Input

    第一行两个正整数(n)(m) ((1leq nleq 100000))

    第二行为(n)个整数(a_i),表示小时候(ycz)的青梅竹马的颜值((1leq a_i<=10^9))

    接下来(m)行,每行为一条信息,每条信息可能是下面的一种:

    (C\, x\, y)表示第(x)个城市的妹子的颜值下降了(y)

    (I\, x\, y)表示在第(x)个城市有一个颜值为(y)的妹子迷上了(ycz)

    (D\, x)表示第(x)个妹子和(ycz)分手了

    (Q)表示(ycz)现在想知道如果现在去找他所有的妹子们珂以获得多大的愉悦度

    说明:妹子们居住的城市编号最大为(5 imes 10^5)

    Output

    对于每一个(Q)输出一个整数

    别看题面这么长,一个裸的线段树.

    支持操作,单点修改&&单点查询.

    难点在于如何分手

    直接(while)去找这个妹子实在左边还是右边就好了.qwq。

    貌似不是很难,记得开$long long $就好

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #define int long long 
    #define R register
    #define N 500008
    
    using namespace std;
    
    inline void in(int &x)
    {
    	int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    
    int n,m,new_n;
    int res[N];
    struct cod{int sum,num,l,r;}tr[N<<2];
    
    #define ls o<<1
    #define rs o<<1|1
    inline void up(int o)
    {
    	tr[o].sum=tr[ls].sum+tr[rs].sum;
    	tr[o].num=tr[ls].num+tr[rs].num;
    }
    
    void build(int o,int l,int r)
    {
    	tr[o].l=l,tr[o].r=r;
    	if(l==r)
    	{
    		tr[o].sum=res[l];
    		tr[o].num= (l<=n ? 1:0);
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    	up(o);
    }
    
    void change(int o,int l,int r,int pos,int del,int flg)
    {
    	if(l==r)
    	{
    		tr[o].sum+=del;
    		tr[o].num=flg;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(pos<=mid)change(ls,l,mid,pos,del,flg);
    	else change(rs,mid+1,r,pos,del,flg);
    	up(o);
    }
    
    int query(int o,int l,int r,int x,int y)
    {
    	if(x<=l and y>=r)return tr[o].sum;
    	int mid=(l+r)>>1,res=0;
    	if(x<=mid)res+=query(ls,l,mid,x,y);
    	if(y>mid)res+=query(rs,mid+1,r,x,y);
    	return res;
    }
    
    int pos;
    
    int t_query(int o,int k)
    {
    	while(2333)
    	{
    		if(tr[o].l==tr[o].r)
    		{
    			pos=tr[o].l;
    			return tr[o].sum;
    		}
    		if(tr[ls].num>=k)o=ls;
    		else
    		{
    			k-=tr[ls].num;
    			o=rs;
    		}
    	}
    }
    
    char opt[7];
    signed main()
    {
    	in(n),in(m);
    	for(R int i=1;i<=n;i++)in(res[i]);
    	new_n=N;
    	build(1,1,new_n);
    	for(R int i=1,x,y;i<=m;i++)
    	{
    		scanf("%s",opt+1);
    		if(opt[1]=='C')
    		{
    			in(x),in(y);
    			change(1,1,new_n,x,-y,1);
    		}
    		if(opt[1]=='I')
    		{
    			in(x),in(y);
    			int now=query(1,1,new_n,x,x);
    			change(1,1,new_n,x,y-now,1);
    		}
    		if(opt[1]=='D')
    		{
    			in(x);
    			int now=t_query(1,x);
    			change(1,1,new_n,pos,-now,0);
    		}
    		if(opt[1]=='Q')
    			printf("%lld
    ",tr[1].sum);
    	}
    }
    
  • 相关阅读:
    小程序-自定义组件
    51Nod
    CodeForces
    JSON、闭包和原型----透视Javascript语言核心
    转载:动态规划法总结
    to初学者:从汉诺塔问题深入理解递归算法思想
    不知‘时间复杂度’所云的看过来
    盲点流水账记录
    常用序列化协议总结
    排序——了解总体以及插入排序
  • 原文地址:https://www.cnblogs.com/-guz/p/9866286.html
Copyright © 2020-2023  润新知