码迷,mamicode.com
首页 > 其他好文 > 详细

线段树【p4879】ycz的妹子

时间:2018-10-28 19:17:38      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:fine   负数   scanf   block   std   %s   print   turn   lse   

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\) \((1\leq n\leq 100000)\)

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

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

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

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

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

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

说明:妹子们居住的城市编号最大为\(5\times 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\n",tr[1].sum);
    }
}

线段树【p4879】ycz的妹子

标签:fine   负数   scanf   block   std   %s   print   turn   lse   

原文地址:https://www.cnblogs.com/-guz/p/9866286.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!