看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;
}