Yaroslav and Points CF 295E

22 篇文章 0 订阅
7 篇文章 0 订阅

Tutorial理解了信息维护的办法,CF很人性化啊,以后转战CF。

这题线段树和splay都可以搞。

线段树:

需要离散化,一开始Move the pj-th理解成了当前序列第pj小的元素,心说这咋离散化啊,

尼玛还要再建个平衡树维护离散化过程,也太恶心吧,又看了下要求是初始的第pj个元素,

这就好办了,不过线段树搞这种题赶脚好麻烦,以后遇到需要移动元素的还是果断splay吧




#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream>
#include <utility>   
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;

const int MAXN(200010);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI(2000000000);
const int MOD(10000);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);

struct ELE
{
	int num;
	bool flag;
	friend bool operator < (const ELE &op1, const ELE &op2)
	{
		return op1.num == op2.num? op1.flag: op1.num < op2.num;
	}
};

ELE table[MAXN];
int quant;
int arr[100010], tarr[100010];

struct SEGMENT_TREE
{
	struct NODE
	{
		LL sum, ans;
		int size;
	};
	NODE node[MAXN << 2];
	inline int lson(int sour){return sour << 1;}
	inline int rson(int sour){return (sour << 1)|1;}
	void push_up(NODE &sour, NODE &ls, NODE &rs)
	{
		sour.size = ls.size+rs.size;
		sour.sum = ls.sum+rs.sum;
		sour.ans = ls.size*rs.sum-ls.sum*rs.size+ls.ans+rs.ans;
	}
	
	void build(int l, int r, int rt)
	{
		if(l == r)
		{
			node[rt].ans = 0;
			node[rt].size = table[l].flag? 1: 0;
			node[rt].sum = table[l].flag? table[l].num: 0;
			return;
		}
		int m = (l+r) >> 1;
		build(l, m, lson(rt));
		build(m+1, r, rson(rt));
		push_up(node[rt], node[lson(rt)], node[rson(rt)]);
	}
	
	int goal, flag, value;
	void change(int l, int r, int rt)
	{
		if(l == r)
		{
			node[rt].size = flag? 1: 0;
			node[rt].sum = flag? value: 0;
			return;
		}
		int m = (l+r) >> 1;
		if(goal <= m)
			change(l, m, lson(rt));
		else
			change(m+1, r, rson(rt));
		push_up(node[rt], node[lson(rt)], node[rson(rt)]);
	}
	int select(int l, int r, int rt, int kth)
	{
		if(l == r)
			return l;
		int m = (l+r) >> 1;
		if(kth <= node[lson(rt)].size)
			return select(l, m, lson(rt), kth);
		else
			return select(m+1, r, rson(rt), kth-node[lson(rt)].size);
	}
	int ql, qr;
	void query(int l, int r, int rt, NODE &ret)
	{
		if(ql <= l && qr >= r)
		{
			ret = node[rt];
			return ;
		}
		int m = (l+r) >> 1;
		NODE t1, t2;
		if(ql <= m)
			query(l, m, lson(rt), t1);
		else
			t1.ans = t1.sum = t1.size = 0;
		if(qr > m)
			query(m+1, r, rson(rt), t2);
		else
			t2.ans = t2.sum = t2.size = 0;
		push_up(ret, t1, t2);
	}
};

SEGMENT_TREE st;

int find(int goal)
{
	int l = 1, r = quant+1;
	while(l < r)
	{
		int m = (l+r) >> 1;
		if(table[m].num < goal)
			l = m+1;
		else
			r = m;
	}
	return l;
}

int op[100010][3];

int main()
{
	int n;
	while(~scanf("%d", &n))
	{
		quant = 0;
		table[++quant].num = -INFI;
		table[quant].flag = true;
		table[++quant].num = INFI;
		table[quant].flag = true;
		for(int i = 1; i <= n; ++i)
		{
			scanf("%d", arr+i);
			table[++quant].num = tarr[i] = arr[i];
			table[quant].flag = true;
		}
		int m;
		scanf("%d", &m);
		for(int i = 1; i <= m; ++i)
		{
			scanf("%d%d%d", op[i], op[i]+1, op[i]+2);
			if(op[i][0] == 1)
			{
				arr[op[i][1]] += op[i][2];
				table[++quant].num = arr[op[i][1]];
				table[quant].flag = false;
			}
		}
		sort(table+1, table+1+quant);
		int temp = quant;
		quant = 1;
		for(int i = 2; i <= temp; ++i)
			if(table[i].num != table[quant].num)
				table[++quant] = table[i];
		st.build(1, quant, 1);
		for(int i = 1; i <= m; ++i)
		{
			if(op[i][0] == 1)
			{
				int ind = find(tarr[op[i][1]]);
				st.goal = ind;
				st.flag = 0;
				st.change(1, quant, 1);
				tarr[op[i][1]] += op[i][2];
				ind = find(tarr[op[i][1]]);
				st.goal = ind;
				st.flag = 1;
				st.value = tarr[op[i][1]];
				st.change(1, quant, 1);
			}
			else
			{
				int ind = find(op[i][1]);
				st.ql = ind;
				ind = find(op[i][2]);
				if(table[ind].num > op[i][2]) --ind;
				st.qr = ind;
				SEGMENT_TREE::NODE ans;
				st.query(1, quant, 1, ans);
				printf("%I64d\n", ans.ans);
			}
		}
	}
	return 0;
}

SPLAY:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream>
#include <utility>   
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;

const int MAXN(100015);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI(2000000000);
const int MOD(10000);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);

int arr[MAXN];
int tarr[MAXN];

struct SPLAY_TREE
{
    struct NODE
    {
        int num, size;
        LL sum, ans;
        NODE *fa;
        NODE *ch[2];
    };

    NODE pool[MAXN];
    NODE *root, *NIL, *rear;
    inline void push_up(NODE *sour)  //一定要注意NIL节点对push_up的影响
    {
        NODE *ls = sour->ch[0], *rs = sour->ch[1];
        LL temp;
        temp = (LL)sour->num*ls->size-ls->sum+ls->ans;  //小心这里暴int
        sour->ans = (ls->size+1)*rs->sum-(ls->sum+sour->num)*rs->size+temp+rs->ans;
        sour->size = ls->size+rs->size+1;
        sour->sum = ls->sum+rs->sum+sour->num;
    }
   
    void initNIL()
    {
        NIL->ch[0] = NIL->ch[1] = NIL->fa = NIL;
        NIL->sum = NIL->ans = 0;
        NIL->size = 0;
    }

    void init(int n)
    {
        NIL = pool;
        initNIL();
        rear = pool+1;
        newnode(root, NIL, -INFI);  //插入无穷小
        newnode(root->ch[1], root, INFI); //插入无穷大
        build_tree(root->ch[1]->ch[0], root->ch[1], 1, n); //建树
        push_up(root->ch[1]);
        push_up(root);
    }

    void newnode(NODE *&sour, NODE *f, int num)
    {
        sour = rear++;
        sour->sum = sour->num = num;
        sour->ans = 0;
        sour->size = 1;
        sour->fa = f;
        sour->ch[0] = sour->ch[1] = NIL;
    }

    void build_tree(NODE *&sour, NODE *f, int l, int r)
    {
        if(l > r)
            return;
        int m = (l+r) >> 1;
        newnode(sour, f, arr[m]);
        build_tree(sour->ch[0], sour, l, m-1);
        build_tree(sour->ch[1], sour, m+1, r);
        push_up(sour);
    }

    void rotate(NODE *sour, int flag)
    {
        NODE *f = sour->fa;
    //  push_down(f);
    //  push_down(sour);
        f->ch[!flag] = sour->ch[flag];
        sour->ch[flag]->fa = f;
        sour->fa = f->fa;
        if(f->fa != NIL)
            f->fa->ch[f->fa->ch[1] == f] = sour;
        sour->ch[flag] = f;
        f->fa = sour;
        push_up(f);
    }
    
    void splay(NODE *sour, NODE *goal)
    {
    //  push_down(sour);
        while(sour->fa != goal)
        {
            if(sour->fa->fa == goal)
                rotate(sour, sour->fa->ch[0] == sour);
            else
            {
                NODE *f = sour->fa;
                int flag = (f->fa->ch[0] == f);
                if(f->ch[flag] == sour)
                    rotate(sour, !flag);
                else
                    rotate(f, flag);
                rotate(sour, flag);
            }
        }
        push_up(sour);
        if(goal == NIL)
            root = sour;
    }

    NODE *select(NODE *sour, int r)
    {
        while(sour != NIL)
        {
        //  push_down(sour);
            if(r == sour->ch[0]->size+1)
                break;
            if(r <= sour->ch[0]->size)
                sour = sour->ch[0];
            else
            {
                r -= sour->ch[0]->size+1;
                sour = sour->ch[1];
            }
        }
        return sour;
    }
    inline void pick(int pos1, int pos2)
    {
        NODE *tp = select(root, pos1);
        splay(tp, NIL);
        tp = select(root, pos2+2);
        splay(tp, root);
    }
    int goal;
    NODE *pre(NODE *sour)
    {
        if(sour == NIL)
            return NIL;
        if(goal <= sour->num)
            return pre(sour->ch[0]);
        else
        {
            NODE *temp = pre(sour->ch[1]);
            return temp == NIL? sour: temp;
        }
    }
    NODE *suc(NODE *sour)
    {
        if(sour == NIL)
            return NIL;
        if(goal < sour->num)
        {
            NODE *temp = suc(sour->ch[0]);
            return temp == NIL? sour: temp;
        }
        else
            return suc(sour->ch[1]);    
    }
    void MOVE(int cod, int d)
    {
        NODE *tp1, *tp2;
        goal = cod;
        tp1 = pre(root);
        splay(tp1, NIL);
        tp1 = suc(root);
        splay(tp1, root);
        tp2 = tp1->ch[0];
        tp1->ch[0] = NIL;
        push_up(root->ch[1]);
        push_up(root);
        tp2->num = tp2->sum = goal = cod+d;
        tp2->ans = 0;
        tp1 = pre(root);
        splay(tp1, NIL);
        tp1 = suc(root);
        splay(tp1, root);
        tp1->ch[0] = tp2;
        tp2->fa = tp1;
        push_up(root->ch[1]);
        push_up(root);
    }
    LL QUERY(int l, int r)
    {
        goal = l;
        NODE *tp1 = pre(root);
        splay(tp1, NIL);
        goal = r;
        tp1 = suc(root);
        splay(tp1, root);
        return tp1->ch[0]->ans;
    }
};

SPLAY_TREE spt;

int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        for(int i = 1; i <= n; ++i)
            scanf("%d", arr+i), tarr[i] = arr[i];
        sort(arr+1, arr+1+n);
        spt.init(n);
        int m;
        scanf("%d", &m);
        int op1, op2, op3;
        for(int i = 0; i < m; ++i)
        {
            scanf("%d%d%d", &op1, &op2, &op3);
            if(op1 == 1)
            {
                spt.MOVE(tarr[op2], op3);
                tarr[op2] += op3;
            }
            else
            {
                LL temp = spt.QUERY(op2, op3);
                printf("%I64d\n", temp);
            }
        }
    }
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值