HDU 3726 Graph and Queries
http://acm.hdu.edu.cn/showproblem.php?pid=3726
离线逆序操作启发式合并找第K大值
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 50005
struct Treap
{
int root[N] , priority[N] , child[N][2];
int key[N];
int Size[N] , cnt[N];
vector del;
Treap()
{
priority[0] = 0x7FFFFFFF;
}
void clear()
{
del.clear();
}
int size(int x)
{
return Size[root[x]];
}
void update(int x)
{
Size[x] = Size[child[x][0]] + Size[child[x][1]] + cnt[x];
}
void rotate (int& x , int t)
{
int y = child[x][t];
child[x][t] = child[y][t ^ 1];
child[y][t ^ 1] = x;
update(x) , update(y);
x = y;
}
void __insert(int& x , int k)
{
if (x)
{
if (key[x] == k)
++ cnt[x];
else
{
int t = key[x] < k;
__insert(child[x][t] , k);
if (priority[child[x][t]] < priority[x])
rotate(x , t);
}
}
else
{
x = del.back();
del.pop_back();
key[x] = k;
cnt[x] = 1;
priority[x] = rand() << 15 | rand();
child[x][0] = child[x][1] = 0;
}
update(x);
}
void __erase(int& x , int k)
{
//if (!x) return;
if (key[x] == k)
{
if (cnt[x] > 1)
-- cnt[x];
else
{
if (!child[x][0] && !child[x][1])
{
del.push_back(x);
cnt[x] = 0 , x = 0;
return;
}
int t = priority[child[x][0]] > priority[child[x][1]];
rotate(x , t);
__erase(x , k);
}
}
else
__erase(child[x][key[x] < k] , k);
update(x);
}
int __getKth(int& x , int k)
{
if (k <= Size[child[x][0]])
return __getKth(child[x][0] , k);
k -= Size[child[x][0]] + cnt[x];
if (k <= 0) return key[x];
return __getKth(child[x][1] , k);
}
void merge(int& x , int& y)
{
if (child[x][0]) merge(child[x][0] , y);
if (child[x][1]) merge(child[x][1] , y);
int z = key[x];
while(cnt[x] > 1)
{
__erase(x , z);
if (z != -1 << 30)
__insert(y , z);
}
__erase(x , z);
if (z != -1 << 30)
__insert(y , z);
}
};
#define Nnum 20005
#define Mnum 60005
#define Qnum 500005
int n , m , Q , ca;
Treap T;
struct edge
{
int x , y;
bool f;
}e[Mnum];
struct query
{
int id , x , y;
}q[Qnum];
int f[Nnum] , a[Nnum];
int getf(int x) {return x == f[x] ? x : f[x] = getf(f[x]);}
void work()
{
int i , j , x , y , z;
char str[3];
for (i = 1 ; i <= n ; ++ i)
scanf("%d",&a[i]) , f[i] = i;
for (i = 1 ; i <= m ; ++ i)
scanf("%d%d",&e[i].x, &e[i].y) , e[i].f = 0;
Q = 0 , T.clear();
for (i = n + n/2; i > 0 ; -- i)
T.del.push_back(n + i);
while (scanf("%s" , str) , str[0] != 'E')
{
if (str[0] == 'D')
q[++ Q].id = 0;
if (str[0] == 'Q')
q[++ Q].id = 1;
if (str[0] == 'C')
q[++ Q].id = 2;
scanf("%d",&q[Q].x);
if (q[Q].id)
scanf("%d",&q[Q].y);
if (q[Q].id == 0)
{
e[q[Q].x].f = 1;
}
if (q[Q].id == 2)
{
q[Q].y -= a[q[Q].x];
a[q[Q].x] += q[Q].y;
}
}
for (i = 1 ; i <= m ; ++ i)
if (!e[i].f)
f[getf(e[i].x)] = getf(e[i].y);
for (i = 1 ; i <= n ; ++ i)
{
T.root[i] = i;
T.cnt[i] = 0 , T.priority[i] = INT_MIN , T.key[i] = -1 << 30;
T.child[i][0] = T.child[i][1] = 0;
x = i;
T.__insert(T.root[i] , a[i]);
}
for (i = 1 ; i <= n ; ++ i)
if (getf(i) != i)
{
T.__erase(T.root[i] , a[i]) ;
T.__insert(T.root[getf(i)] , a[i]);
}
long long ans = 0 , tot = 0;
for (i = Q ; i > 0 ; -- i)
{
if (q[i].id == 0)
{
j = q[i].x;
x = getf(e[j].x) , y = getf(e[j].y);
if (x == y) continue;
if (T.size(x) > T.size(y))
swap(x , y);
f[x] = y;
T.merge(T.root[x] , T.root[y]);
}
if (q[i].id == 1)
{
x = getf(q[i].x) , ++ tot;
j = T.size(x);
if (q[i].y < 1 || q[i].y > j)
continue;
ans += T.__getKth(T.root[x] , j - q[i].y + 1);
}
if (q[i].id == 2)
{
x = getf(q[i].x);
T.__erase(T.root[x] , a[q[i].x]);
a[q[i].x] -= q[i].y;
T.__insert(T.root[x] , a[q[i].x]);
}
}
printf("Case %d: %lf\n" , ++ ca , tot ? 1.0 * ans / tot : 0.0);
}
int main()
{
//srand((unsigned int)time(0));
while (scanf("%d%d",&n,&m) , n || m)
//int _; cin >> _;while (_--)
work();
return 0;
}
SCU4285
http://cstest.scu.edu.cn/soj/problem.action?id=4285
可以拿set简单过的,用Treap写了写体会了一下如何进行垃圾回收
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 10005
struct Treap
{
int root , nodecnt , priority[N] , child[N][2];
int key[N];
int Size[N] , cnt[N];
vector del;
Treap(){
del.clear();
root = 0 , nodecnt = 1;
priority[0] = key[0] = 1 << 30;
Size[0] = 0;
}
void clear()
{
del.clear();
root = 0 , nodecnt = 1;
priority[0] = -1 << 30 , key[0] = -1<<30;
Size[0] = 0;
}
int size()
{
return Size[root];
}
void update(int x)
{
Size[x] = Size[child[x][0]] + Size[child[x][1]] + cnt[x];
}
void rotate (int& x , int t)
{
int y = child[x][t];
child[x][t] = child[y][t ^ 1];
child[y][t ^ 1] = x;
update(x) , update(y);
x = y;
}
void __insert(int& x , int k)
{
if (x)
{
if (key[x] == k)
x = x;//++ cnt[x];
else
{
int t = key[x] < k;
__insert(child[x][t] , k);
if (priority[child[x][t]] > priority[x])
rotate(x , t);
}
}
else
{
if (del.size())
{
x = del.back();
del.pop_back();
}
else x = nodecnt ++;
key[x] = k;
cnt[x] = 1;
priority[x] = rand();
child[x][0] = child[x][1] = 0;
}
update(x);
}
void __erase(int& x , int k)
{
if (!x) return;
if (key[x] == k)
{
// if (cnt[x] > 1)
// -- cnt[x];
// else
{
if (!child[x][0] && !child[x][1])
{
del.push_back(x);
x = 0;
return;
}
int t = priority[child[x][0]] < priority[child[x][1]];
rotate(x , t);
__erase(x , k);
}
}
else
__erase(child[x][key[x] < k] , k);
update(x);
}
int __getKth(int& x , int k)
{
if (k <= Size[child[x][0]])
return __getKth(child[x][0] , k);
k -= Size[child[x][0]] + cnt[x];
if (k <= 0) return key[x];
return __getKth(child[x][1] , k);
}
void insert(int x){
__insert(root , x);}
void erase(int x){
__erase(root , x);}
int getKth(int x){
return __getKth(root , x);}
};
int n , m ;
Treap mx , mn;
void work()
{
int i , x , y;
scanf("%d",&n);
mx.clear() , mn.clear();
while (n --)
{
scanf("%d",&m);
while (m --)
{
scanf("%d",&x);
mx.insert(x);
if (mx.size() > n + 3)
mx.erase(mx.getKth(1));
mn.insert(x) ;
if (mn.size() > n + 3)
mn.erase(mn.getKth(mn.size()));
}
if (mx.size() < 2 || mn.size() < 2)
puts("-1 -1");
else
{
x = mn.getKth(2);
y = mx.getKth(mx.size() - 1);
printf("%d %d\n" , x , y);
mx.erase(x) , mn.erase(x);
mx.erase(y) , mn.erase(y);
}
}
}
int main()
{
int _; cin >> _;while (_--)
work();
return 0;
}
区间互不包含这个条件非常强呀……区间排序之后从左往右扫一遍出解
int n , m , ans[N] , a[N];
struct query
{
int l , r , k , num;
bool operator < (const query& p) const{
if(l == p.l)
return r < p.r;
return l < p.l;}
}q[N];
Treap T;
void work()
{
int i , x , y , j;
scanf("%d%d",&n,&m);
for (i = 1 ; i <= n ; ++ i)
scanf("%d",&a[i]);
for (i = 0 ; i < m ; ++ i)
scanf("%d%d%d",&q[i].l , &q[i].r , &q[i].k) , q[i].num = i;
sort(q , q + m);
x = 0 , y = 1;
for (i = 0 ; i < m ; ++ i)
{
while (q[i].r > x)
T.insert(a[++ x]);
while (q[i].l > y)
T.erase(a[y ++]);
ans[q[i].num] = T.getKth(q[i].k);
}
for (i = 0 ; i < m ; ++ i)
printf("%d\n" , ans[i]);
}
http://poj.org/problem?id=2750
线段树,维护区间的权值和最大和最小的段
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100005
#define M 1000005
int n , m , a[N];
struct stree
{
int sum;
int lmax , rmax , smax;
int lmin , rmin , smin;
}t[N << 1];
int id(int l , int r) {return l + r | l != r;}
#define MID int mid = (l + r) >> 1;
#define ID id(l , r)
#define Left l , mid
#define Right mid + 1 , r
void pushup(int l , int r)
{
MID; int p = ID , LL = id(Left) , RR = id(Right);
t[p].sum = t[LL].sum + t[RR].sum;
t[p].lmax = max(t[LL].sum + t[RR].lmax , t[LL].lmax);
t[p].rmax = max(t[RR].sum + t[LL].rmax , t[RR].rmax);
t[p].smax = max(t[LL].rmax + t[RR].lmax , max(t[LL].smax , t[RR].smax));
t[p].lmin = min(t[LL].sum + t[RR].lmin , t[LL].lmin);
t[p].rmin = min(t[RR].sum + t[LL].rmin , t[RR].rmin);
t[p].smin = min(t[LL].rmin + t[RR].lmin , min(t[LL].smin , t[RR].smin));
}
void update(int l , int r , int i , int x)
{
if (l == r) {
int p = ID; t[p].sum = x;
t[p].lmax = t[p].rmax = t[p].smax = x;
t[p].lmin = t[p].rmin = t[p].smin = x;
return;}
if (l == r) return; MID;
if (i <= mid) update(Left , i , x);
if (i > mid) update(Right , i , x);
pushup(l , r);
}
void Build(int l , int r)
{
if (l == r) {
int p = ID; t[p].sum = a[l];
t[p].lmax = t[p].rmax = t[p].smax = a[l];
t[p].lmin = t[p].rmin = t[p].smin = a[l];
return;}
MID;Build(Left);Build(Right);pushup(l , r);
}
void work()
{
int i , x , y , p , ans = 0;
scanf("%d",&n);
for (i = 1 ; i <= n ; ++ i)
scanf("%d",&a[i]);
Build(1 , n) , p = id(1 , n);
scanf("%d",&m);
while (m --)
{
scanf("%d%d",&x,&y);
update(1 , n , x , y);
ans = t[p].sum - t[p].smin;
if (t[p].sum != t[p].smax)
ans = max(t[p].smax , ans);
printf("%d\n" , ans);
}
}
int main()
{
work();
return 0;
}
BZOJ1503 [NOI2004]郁闷的出纳员
http://www.lydsy.com/JudgeOnline/problem.php?id=1503
简单的Treap操作
int n , Q;
Treap T;
void work()
{
int i , x , y , ans = 0 , add = 0; char str[5];
scanf("%d%d",&n,&Q);
T.clear();
while (n --)
{
scanf("%s" , str);
if (*str == 'I')
{
scanf("%d",&x);
if (x < Q);
// ++ ans;
else T.insert(x - add);
}
if (*str == 'S')
{
scanf("%d",&x);
add -= x;
while (T.size() && (y = T.getKth(1)) + add - Q < 0)
T.erase(y) , ++ ans;
}
if (*str == 'A')
{
scanf("%d",&x);
add += x;
}
if (*str == 'F')
{
scanf("%d",&x);
if (x > T.size())
puts("-1");
else printf("%d\n" , T.getKth(T.size() - x + 1) + add);
}
}
printf("%d" , ans);
}
http://www.lydsy.com/JudgeOnline/problem.php?id=1208
multiset也能过
int n;
Treap pet[2];
void work()
{
int i , x , k , l , r , ans = 0;
pet[0].clear() , pet[1].clear();
scanf("%d",&n);
while (n --)
{
scanf("%d%d",&i,&x);
if (!pet[i].size())
pet[i ^ 1].insert(x);
else
{
k = pet[i].Rank(x);
if (k == 0)
{
r = pet[i].getKth(1);
ans += abs(r - x) , ans %= 1000000;
pet[i].erase(r);
continue;
}
if (k == pet[i].size())
{
l = pet[i].getKth(pet[i].size());
ans += abs(l - x) , ans %= 1000000;
pet[i].erase(l);
continue;
}
l = pet[i].getKth(k);
if (l == x) continue;
r = pet[i].getKth(k + 1);
if (abs(l - x) <= abs(r - x))
ans += abs(l - x) , ans %= 1000000 , pet[i].erase(l);
else ans += abs(r - x) , ans %= 1000000 , pet[i].erase(r);
}
}
printf("%d\n" , ans);
}
http://www.lydsy.com/JudgeOnline/problem.php?id=1798
线段树,注意标记下传的顺序
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100005
#define M 1000005
int n , m , a[N] , Q;
struct stree
{
long long sum , multi , add;
}t[N << 1];
int id(int l , int r) {return l + r | l != r;}
#define MID int mid = (l + r) >> 1;
#define ID id(l , r)
#define Left l , mid
#define Right mid + 1 , r
void Multi(int Id , int x)
{
t[Id].multi = t[Id].multi * x % Q;
t[Id].sum = t[Id].sum * x % Q;
t[Id].add = t[Id].add * x % Q;
}
void pushup(int l , int r)
{
MID; int p = ID , LL = id(Left) , RR = id(Right);
t[p].sum = (t[LL].sum + t[RR].sum) % Q;
}
void pushdown(int l , int r)
{
MID; int p = ID , LL = id(Left) , RR = id(Right);
if (t[p].multi != 1 % Q)
{
Multi(LL , t[p].multi);
Multi(RR , t[p].multi);
t[p].multi = 1 % Q;
}
if (t[p].add)
{
t[LL].sum = (t[LL].sum + t[p].add * (mid - l + 1)) % Q;
t[LL].add = (t[LL].add + t[p].add) % Q;
t[RR].sum = (t[RR].sum + t[p].add * (r - mid)) % Q;
t[RR].add = (t[RR].add + t[p].add) % Q;
t[p].add = 0;
}
}
void update(int l , int r , int top , int bot , int q , int w)
{
if (top <= l && r <= bot) {int p = ID;
if (q == 1) Multi(ID , w);
if (q == 2) t[p].add = (t[p].add + w) % Q , t[p].sum = (t[p].sum + w * (r - l + 1)) % Q;
return;}MID;pushdown(l , r);
if (top <= mid) update(Left , top , bot , q , w);
if (bot > mid) update(Right , top , bot , q , w);
pushup(l , r);
}
int Query(int l , int r , int top , int bot)
{
if (top <= l && r <= bot) {return t[ID].sum;}MID;pushdown(l , r);int ans = 0;
if (top <= mid) ans += Query(Left , top , bot);
if (bot > mid) ans += Query(Right , top , bot);
pushup(l , r); return ans % Q;
}
void Build(int l , int r)
{
t[ID].multi = 1;
if (l == r) {t[ID].sum = a[l];return;}
MID;Build(Left);Build(Right);pushup(l , r);
}
void work()
{
int i , x , y , c , ans = 0;
scanf("%d%d",&n,&Q);
for (i = 1 ; i <= n ; ++ i)
scanf("%d",&a[i]);
Build(1 , n);
scanf("%d",&m);
while (m --)
{
scanf("%d%d%d",&i,&x,&y);
if (i < 3)
scanf("%d" ,&c) , update(1 , n , x , y , i , c);
else
printf("%d\n" , Query(1 , n , x , y));
}
}
int main()
{
work();
return 0;
}
ZJU2112 Dynamic Rankings
树套树,后来用树状数组套主席树写过但是MLE了,树状数组套主席树的空间消耗的确很大,相应却有优秀的时间效率
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 50005
#define M 1000005
struct Treap
{
int root , nodecnt , priority[M] , child[M][2];
int key[M];
int Size[M] , cnt[M];
vector del;
void clear()
{
root = 0 , nodecnt = 1;
priority[0] = INT_MIN;
child[0][0] = child[0][1] = 0;
key[0] = INT_MIN , cnt[0] = 0 , Size[0] = 0;
del.clear();
}
void update(int x)
{
Size[x] = Size[child[x][0]] + Size[child[x][1]] + cnt[x];
}
void rotate (int& x , int t)
{
int y = child[x][t];
child[x][t] = child[y][t ^ 1];
child[y][t ^ 1] = x;
update(x) , update(y);
x = y;
}
void __insert(int& x , int k)
{
if (x)
{
if (key[x] == k)
++ cnt[x];
else
{
int t = key[x] < k;
__insert(child[x][t] , k);
if (priority[child[x][t]] > priority[x])
rotate(x , t);
}
}
else
{
if (del.size())
{
x = del.back();
del.pop_back();
}
else x = nodecnt ++;
key[x] = k;
cnt[x] = 1;
priority[x] = rand() << 15 | rand();
child[x][0] = child[x][1] = 0;
}
update(x);
}
void __erase(int& x , int k)
{
//if (!x) return;
if (key[x] == k)
{
if (cnt[x] > 1)
-- cnt[x];
else
{
if (!child[x][0] && !child[x][1])
{
del.push_back(x);
cnt[x] = 0 , x = 0;
return;
}
int t = priority[child[x][0]] < priority[child[x][1]];
rotate(x , t);
__erase(x , k);
}
}
else
__erase(child[x][key[x] < k] , k);
update(x);
}
int __Rank(int& x , int k)
{
if(!x) return 0;
if (k < key[x])
return __Rank(child[x][0] , k);
int Rk = Size[child[x][0]] + cnt[x];
if (k > key[x])
Rk += __Rank(child[x][1] , k);
return Rk;
}
int __getKth(int& x , int k)
{
if (k <= Size[child[x][0]])
return __getKth(child[x][0] , k);
k -= Size[child[x][0]] + cnt[x];
if (k <= 0) return key[x];
return __getKth(child[x][1] , k);
}
/*void insert(int x){
__insert(root , x);}
void erase(int x){
__erase(root , x);}
int getKth(int x){
return __getKth(root , x);}*/
};
int n , m , a[N] , ans;
Treap T;
int t[N << 1];
int id(int l , int r) {return l + r | l != r;}
#define MID int mid = (l + r) >> 1;
#define ID id(l , r)
#define Left l , mid
#define Right mid + 1 , r
void SInsert(int l , int r , int i , int x)
{
T.__insert(t[ID] , x);
if (l == r) return; MID;
if (i <= mid) SInsert(Left , i , x);
if (i > mid) SInsert(Right , i , x);
}
void SErase(int l , int r , int i , int x)
{
T.__erase(t[ID] , x);
if (l == r) return; MID;
if (i <= mid) SErase(Left , i , x);
if (i > mid) SErase(Right , i , x);
}
void SQuery(int l , int r , int top , int bot , int x)
{
if (top <= l && r <= bot) {ans += T.__Rank(t[ID] , x); return;} MID;
if (top <= mid) SQuery(Left , top , bot , x);
if (bot > mid) SQuery(Right , top , bot , x);
}
void work()
{
int i , x , y , l , r , mid , p; char s[5];
memset(t , 0 , sizeof(t)) , T.clear();
memset(a , 0 , sizeof(a));
scanf("%d%d" ,&n,&m);
for (i = 1 ; i <= n ; ++ i)
scanf("%d",&a[i]) , SInsert(1 , n , i , a[i]);
while (m --)
{
scanf("%s" , s);
if (*s == 'C')
{
scanf("%d%d",&x,&y);
SErase(1 , n , x , a[x]);
a[x] = y;
SInsert(1 , n , x , a[x]);
}
else
{
scanf("%d%d%d",&x,&y,&p);
l = 0 , r = 1 << 30;
while (l < r)
{
mid = (l + r) >> 1 , ans = 0;
SQuery(1 , n , x , y , mid);
if(ans < p) l = mid + 1; else r = mid;
}
printf("%d\n" , l);
}
}
}
int main()
{
freopen("~input.txt","r",stdin);
//srand((unsigned int)time(0));
//while (scanf("%d%d",&n,&m) , n || m)
int _; cin >> _;while (_--)
work();
return 0;
}
线段树维护树的DFS序列,这样边权的变换和询问都可以转换到一个区间上的问题。
都有DFS序列了所以求LCA可以转成RMQ,但是还是偷懒直接倍增LCA了
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100005
#define M 1000005
int n , mcnt , pre[N] , f[N][17] , m , dis[N] , dep[N];
int cnt , begin[N] , end[N] , a[N] , ans;
struct edge
{
int x , w , next;
}e[N << 1];
struct stree
{
int w , f;
} t[N << 1];
int id(int l , int r) {return l + r | l != r;}
#define MID int mid = (l + r) >> 1;
#define ID id(l , r)
#define Left l , mid
#define Right mid + 1 , r
void pushup(int l , int r)
{
MID;t[ID].w = max(t[id(Left)].w , t[id(Right)].w);
}
void pushdown(int l , int r)
{
MID ;int p = ID , LL = id(Left) , RR = id(Right);
if (t[p].f)
{
t[LL].w += t[p].f , t[LL].f += t[p].f ;
t[RR].f += t[p].f , t[RR].w += t[p].f ;
t[p].f = 0;
}
}
void Build(int l , int r)
{
if (l == r) {t[ID].w = a[l]; t[ID].f = 0 ;return;}
MID;Build(Left);Build(Right);pushup(l , r);
}
void Query(int l , int r , int top , int bot)
{
if (top <= l && r <= bot) {ans = max(ans , t[ID].w); return;}
MID; pushdown(l , r);
if (top <= mid) Query(Left , top , bot);
if (bot > mid) Query(Right , top , bot);
pushup(l , r);
}
void Update(int l , int r , int top , int bot , int x)
{
if (top <= l && r <= bot) {t[ID].f += x , t[ID].w += x; return;}
MID; pushdown(l , r);
if (top <= mid) Update(Left , top , bot , x);
if (bot > mid) Update(Right , top , bot , x);
pushup(l , r);
}
void dfs(int x , int fa , int d , int w , int p)
{
f[x][0] = fa , dis[x] = w , a[++ cnt] = d , begin[x] = cnt , dep[x] = p;
for (int i = pre[x] ; ~i ; i = e[i].next)
if (e[i].x != fa)
dfs(e[i].x , x , d + e[i].w , e[i].w , p + 1);
end[x] = cnt;
}
int LCA(int x , int y)
{
int log , i ;
if (dep[x] < dep[y]) swap(x , y); // x is deeper than y
for (log = 1 ; (1 << log) <= dep[x] ; ++ log); -- log;
for (i = log ; i >= 0 ; -- i)
if (dep[x] - (1 << i) >= dep[y])
x = f[x][i];
if (x == y) return y; // y is ancstor of x
for (i = log ; i >= 0 ; -- i)
if (f[x][i] && f[x][i] != f[y][i])
x = f[x][i] , y = f[y][i];
return f[x][0];
}
void work()
{
int i , j , x , y , z;
scanf("%d",&n);
memset(pre , -1 , sizeof(pre)) , mcnt = 0;
memset(t , 0 , sizeof(t));
memset(a , 0 , sizeof(a));
memset(f , 0 , sizeof(f));
for (i = 1 ; i < n ; ++ i)
{
scanf("%d%d%d",&x,&y,&z);
e[mcnt] = (edge) {y , z , pre[x]} , pre[x] = mcnt ++;
e[mcnt] = (edge) {x , z , pre[y]} , pre[y] = mcnt ++;
}
cnt = 0;
dfs(1 , 0 , 0 , 0 , 0);
for (j = 1 ; 1 << j < n ; ++ j)
for (i = 1 ; i <= n ; ++ i)
f[i][j] = f[f[i][j - 1]][j - 1];
Build(1 , n);
scanf("%d",&m);
int pos = 1;
while (m --)
{
scanf("%d",&i);
if (i == 1)
{
scanf("%d",&x);
y = LCA(x , pos);
ans = -1 << 30; j = 0;
Query(1 , n , begin[x] , begin[x]) , j += ans;
ans = -1 << 30; Query(1 , n , begin[pos] , begin[pos]) , j += ans;
ans = -1 << 30; Query(1 , n , begin[y] , begin[y]) , j -= ans << 1;
printf("%d\n" , j);
pos = x;
}
if (i == 2)
{
ans = -1 << 30;
Query(1 , n , begin[pos] , begin[pos]);
j = ans; ans = -1 << 30;
Query(1 , n , begin[pos] , end[pos]);
printf("%d\n" , ans - j);
}
if (i == 3)
{
scanf("%d%d%d",&x,&y,&z);
if (dep[x] < dep[y]) swap(x , y);
Update(1 , n , begin[x] , end[x] , z - dis[x]);
dis[x] = z;
}
}
}
int main()
{
int _; cin >> _;while (_--)
work();
return 0;
}
HDU2665 Kth number
http://acm.hdu.edu.cn/showproblem.php?pid=2665
看了主席树资料的以后YY写了一个,就拿这道题开刀了维护的是一个离散化之后的权值“前缀和”的东西,其实就是可以理解为开了n棵线段树,但是只占了O(nlogn)的空间。
如果是带单点修改的话就需要用树状数组维护这个前缀和了,想起来也非常顺,但是写ZOJ那道题MLE。。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100005
#define M 2000005
int id(int l , int r) {return l + r | l != r;}
#define MID int mid = (l + r) >> 1;
#define ID id(l , r)
#define Left l , mid
#define Right mid + 1 , r
#define LL child[p][0]
#define RR child[p][1]
struct Functional_stree
{
int nodecnt;
int root[N];
int child[M][2] , sum[M];
void clear()
{
nodecnt = 0;
root[0] = child[0][0] = child[0][1] = sum[0] = 0;
}
int newnode()
{
child[++ nodecnt][0] = child[nodecnt][1] = 0;
sum[nodecnt] = 0;
return nodecnt;
}
void insert(int p , int q , int l , int r , int x)
{
if (l == r) {++ sum[p];return;} MID;
if (x <= mid)
{
LL = newnode() , RR = child[q][1] , sum[LL] = sum[child[q][0]];
insert(LL , child[q][0] , Left , x);
}
if (x > mid)
{
RR = newnode() , LL = child[q][0] , sum[RR] = sum[child[q][1]];
insert(RR , child[q][1] , Right , x);
}
sum[p] = sum[LL] + sum[RR];
}
int Query(int p , int q , int l , int r , int k)
{
if (l == r) return l;MID;
if (sum[LL] - sum[child[q][0]] >= k)
return Query(LL , child[q][0] , Left , k);
return Query(RR , child[q][1] , Right , k - sum[LL] + sum[child[q][0]]);
}
};
Functional_stree t;
int n , a[N] , d[N] , m , Q;
void work()
{
int i , x , y , k;
scanf("%d%d",&m,&Q);
t.clear();
for (i = 1 ; i <= m ; ++ i)
scanf("%d",&a[i]) , d[i] = a[i];
sort(d + 1 , d + m + 1);
n = unique(d + 1 , d + m + 1) - d - 1;
for (i = 1 ; i <= m ; ++ i)
a[i] = lower_bound(d + 1 , d + n + 1 , a[i]) - d;
for (i = 1 ; i <= m ; ++ i)
{
t.root[i] = t.newnode();
t.insert(t.root[i] , t.root[i - 1] , 1 , n , a[i]);
}
while (Q --)
{
scanf("%d%d%d",&x,&y,&k);
printf("%d\n" , d[t.Query(t.root[y] , t.root[x - 1] , 1 , n , k)]);
}
}
int main()
{
int _; cin >> _;while (_--)
work();
return 0;
}
HDU4417 Super Mario
http://acm.hdu.edu.cn/showproblem.php?pid=4417
一段序列求某区间上有多少值<=某个值w
主席树好神好方便啊,就相当于求r这棵树-(l-1)这棵树有多少值<=w..
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100005
#define M 2000005
int id(int l , int r) {return l + r | l != r;}
#define MID int mid = (l + r) >> 1;
#define ID id(l , r)
#define Left l , mid
#define Right mid + 1 , r
#define LL child[p][0]
#define RR child[p][1]
#define QL child[q][0]
#define QR child[q][1]
struct Functional_stree
{
int nodecnt;
int root[N];
int child[M][2] , sum[M];
void clear()
{
nodecnt = 0;
root[0] = child[0][0] = child[0][1] = sum[0] = 0;
}
int newnode()
{
child[++ nodecnt][0] = child[nodecnt][1] = 0;
sum[nodecnt] = 0;
return nodecnt;
}
void insert(int p , int q , int l , int r , int x)
{
if (l == r) {++ sum[p];return;} MID;
if (x <= mid)
{
LL = newnode() , RR = QR , sum[LL] = sum[QL];
insert(LL , QL , Left , x);
}
if (x > mid)
{
RR = newnode() , LL = QL , sum[RR] = sum[QR];
insert(RR , QR , Right , x);
}
sum[p] = sum[LL] + sum[RR];
}
int Query(int p , int q , int l , int r , int k)
{
if (1 <= l && r <= k) return sum[p] - sum[q];MID;
int ans = 0;
if (1 <= mid) ans += Query(LL , QL , Left , k);
if (k > mid) ans += Query(RR , QR , Right , k);
return ans;
}
};
Functional_stree t;
int n , a[N] , d[N] , m , Q , ca;
void work()
{
int i , x , y , k;
scanf("%d%d",&m,&Q);
t.clear();
for (i = 1 ; i <= m ; ++ i)
scanf("%d",&a[i]) , d[i] = a[i];
sort(d + 1 , d + m + 1);
n = unique(d + 1 , d + m + 1) - d - 1;
for (i = 1 ; i <= m ; ++ i)
a[i] = lower_bound(d + 1 , d + n + 1 , a[i]) - d;
for (i = 1 ; i <= m ; ++ i)
{
t.root[i] = t.newnode();
t.insert(t.root[i] , t.root[i - 1] , 1 , n , a[i]);
}
printf("Case %d:\n" , ++ ca);
while (Q --)
{
scanf("%d%d%d",&x,&y,&k) , ++ x , ++ y;
k = upper_bound(d + 1 , d + n + 1 , k) - d - 1;
if (!k) puts("0"); else
printf("%d\n" , t.Query(t.root[y] , t.root[x - 1] , 1 , n , k));
}
}
int main()
{
int _; cin >> _;while (_--)
work();
return 0;
}
http://acm.hdu.edu.cn/showproblem.php?pid=3804
同样用主席树,和上面那道题差不多
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100005
#define M 2000005
int id(int l , int r) {return l + r | l != r;}
#define MID int mid = (l + r) >> 1;
#define ID id(l , r)
#define Left l , mid
#define Right mid + 1 , r
#define LL child[p][0]
#define RR child[p][1]
#define QL child[q][0]
#define QR child[q][1]
struct Functional_stree
{
int nodecnt;
int root[N];
int child[M][2] , sum[M];
void clear()
{
nodecnt = 0;
root[0] = child[0][0] = child[0][1] = sum[0] = 0;
}
int newnode()
{
child[++ nodecnt][0] = child[nodecnt][1] = 0;
sum[nodecnt] = 0;
return nodecnt;
}
void insert(int p , int q , int l , int r , int x)
{
if (l == r) {++ sum[p];return;} MID;
if (x <= mid)
{
LL = newnode() , RR = QR , sum[LL] = sum[QL];
insert(LL , QL , Left , x);
}
if (x > mid)
{
RR = newnode() , LL = QL , sum[RR] = sum[QR];
insert(RR , QR , Right , x);
}
sum[p] = sum[LL] + sum[RR];
}
int rank(int p , int l , int r , int k)
{
if (1 <= l && r <= k) return sum[p]; MID;
int ans = 0;
if (1 <= mid) ans += rank(LL , Left , k);
if (k > mid) ans += rank(RR , Right , k);
return ans;
}
int Query(int p , int l , int r , int k)
{
if (l == r) return l; MID;
if (sum[LL] >= k) return Query(LL , Left , k);
return Query(RR , Right , k - sum[LL]);
}
};
Functional_stree t;
int n , d[N] , m , Q;
struct edge
{
int x , w , next;
}e[N << 1];
int pre[N] , mcnt;
bool f[N];
void BFS()
{
int i , x , y , z; memset(f , 0 , sizeof(f));
queue q; q.push(1) , f[1] = 1;
while (!q.empty())
{
x = q.front() , q.pop();
for (i = pre[x] ; ~i ; i = e[i].next) if (!f[y = e[i].x])
{
z = lower_bound(d + 1 , d + n + 1 , e[i].w) - d;
t.root[y] = t.newnode();
t.insert(t.root[y] , t.root[x] , 1 , n , z);
f[y] = 1 , q.push(y);
}
}
}
void work()
{
int i , x , y , z , k;
scanf("%d",&n) , memset(d , 0 , sizeof(d)) , d[0] = -1;
t.clear() , memset(pre , -1 , sizeof(pre)) , mcnt = 0;
for (i = 1 ; i < n ; ++ i)
{
scanf("%d%d%d",&x,&y,&z) , d[i] = z;
e[mcnt] = (edge) {y , z , pre[x]} , pre[x] = mcnt ++;
e[mcnt] = (edge) {x , z , pre[y]} , pre[y] = mcnt ++;
}
sort(d + 1 , d + n) , n = unique(d + 1 , d + n) - d - 1;
t.root[1] = t.newnode() , BFS();
scanf("%d",&Q);
while (Q --)
{
scanf("%d%d",&x ,&k); if (x == 1) {puts("-1");continue;}
k = upper_bound(d + 1 , d + n + 1 , k) - d - 1;
if (!k) {puts("-1");continue;}k = t.rank(t.root[x] , 1 , n , k);if (!k) {puts("-1");continue;}
printf("%d\n" , d[t.Query(t.root[x] , 1 , n , k)]);
}
}
int main()
{
int _; cin >> _;while (_--)
work();
return 0;
}
http://poj.org/problem?id=3580
维护一段序列。。用可以split和merge的Treap写的,昨天至少调了3个小时。。
写完成就感爆棚啊。。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100005
#define M 2000005
struct Segment_Treap
{
int nodecnt , root;
//int root[N];
int key[M] ;
int priority[M] , add[M] , sum[M] , mn[M];
int l[M] , r[M];
bool rev[M];
vector del;
void clear()
{
nodecnt = 0 , root = 0;
del.clear() , priority[0] = -1 << 30;
//root[0] = child[0][0] = child[0][1] = key[0] = 0;
}
void pushdown(int x)
{
if (rev[x])
{
if(l[x]) swap(l[l[x]] , r[l[x]]) , rev[l[x]] ^= 1;
if(r[x]) swap(l[r[x]] , r[r[x]]) , rev[r[x]] ^= 1;
rev[x] ^= 1;
}
if (add[x])
{
if(l[x]) mn[l[x]] += add[x] , key[l[x]] += add[x] , add[l[x]] += add[x];
if(r[x]) mn[r[x]] += add[x] , key[r[x]] += add[x] , add[r[x]] += add[x];
add[x] = 0;
}
}
void pushup(int x)
{
mn[x] = key[x] , sum[x] = 1;
if (l[x]) mn[x] = min(mn[x] , mn[l[x]]) , sum[x] += sum[l[x]];
if (r[x]) mn[x] = min(mn[x] , mn[r[x]]) , sum[x] += sum[r[x]];
}
void __insert(int& x , int i , int k)
{
if (x)
{
pushdown(x);
if (sum[l[x]] + 1 >= i)
{
__insert(l[x] , i , k);
int y = l[x];
if (priority[y] < priority[x])
{
pushdown(y);
l[x] = r[y] , r[y] = x , x = y;
pushup(r[x]);
}
}
else
{
__insert(r[x] , i - sum[l[x]] - 1 , k);
int y = r[x];
if (priority[y] < priority[x])
{
pushdown(y);
r[x] = l[y] , l[y] = x , x = y;
pushup(l[x]);
}
}
}
else
{
if (del.size())
x = del.back() , del.pop_back();
else x = ++ nodecnt;
mn[x] = key[x] = k , sum[x] = 1;
add[x] = rev[x] = 0;
priority[x] = rand() << 15 | rand();
l[x] = r[x] = 0;
}
pushup(x);
}
void insert(int i , int k) {__insert(root , i , k);}
void merge(int& p , int x , int y)
{
if (!x || !y) p = x | y;
else if (priority[x] < priority[y])
pushdown(x) , merge(r[x] , r[x] , y) , pushup(x) , p = x;
else pushdown(y) , merge(l[y] , x , l[y]) , pushup(y) , p = y;
}
void __erase(int& x , int i)
{
pushdown(x);
if (sum[l[x]] + 1 == i)
{
del.push_back(x);
merge(x , l[x] , r[x]);
}else
if (sum[l[x]] + 1 > i)
__erase(l[x] , i) , pushup(x);
else if (sum[l[x]] + 1 < i)
__erase(r[x] , i - sum[l[x]] - 1) , pushup(x);
}
void erase(int i) {__erase(root , i);}
void split(int p , int& x , int& y , int i)
{
if (!i) {x = 0 ; y = p;return;}
if (i == sum[p]) {x = p ; y = 0;return;}
pushdown(p);
if (sum[l[p]] >= i)
{
y = p;
split(l[p] , x , l[y] , i);
pushup(y);
}
else
{
x = p;
split(r[p] , r[x] , y , i - sum[l[p]] - 1);
pushup(x);
}
}
int __query(int x , int a , int b)
{
if (a == 1 && b == sum[x]) return mn[x];
pushdown(x);
int u = sum[l[x]] + 1;
int p = (a <= u && u <= b ? key[x] : 1 << 30);
if (a < u) p = min(p , __query(l[x] , a , b >= u ? u - 1 : b));
if (b > u) p = min(p , __query(r[x] , a <= u ? 1 : a - u , b - u));
return p;
}
int query(int a , int b) {return __query(root , a , b);}
int Reverse(int a , int b)
{
int x , y , z;
split(root , x , y , a - 1);
split(y , y , z , b - a + 1);
rev[y] ^= 1 , swap(l[y] , r[y]);
merge(x , x , y);
merge(root , x , z);
}
int Add(int a , int b , int c)
{
int x , y , z;
split(root , x , y , a - 1);
split(y , y , z , b - a + 1);
key[y] += c , mn[y] += c , add[y] += c;
merge(x , x , y);
merge(root , x , z);
}
int Revolve(int a , int b , int c)
{
int w , x , y , z;
split(root , w , x , a - 1);
split(x , x , y , b - a + 1);
split(y , y , z , c - b);
merge(w , w , y);
merge(w , w , x);
merge(root , w , z);
}
};
Segment_Treap T;
void work()
{
int n , i , x , y , z , m; char str[50];
scanf("%d",&n);T.clear();
for (i = 1 ; i <= n ; ++ i)
scanf("%d",&x) , T.insert(i , x);
scanf("%d",&m);
while (m --)
{
scanf("%s" , str);
if (*str == 'A')
{
scanf("%d%d%d",&x,&y,&z);
T.Add(x , y , z);
}else
if (*str == 'I')
{
scanf("%d%d",&x,&y);
T.insert(x + 1 , y);
}else
if (*str == 'D')
{
scanf("%d",&x);
T.erase(x);
}else
if (*str == 'M')
{
scanf("%d%d",&x,&y);
printf("%d\n" , T.query(x , y));
}else
if (*(str + 3) == 'E')
{
scanf("%d%d",&x,&y);
T.Reverse(x , y);
}else
{
scanf("%d%d%d",&x,&y,&z);
z = (z % (y - x + 1) + y - x + 1) % (y - x + 1);
if (z) T.Revolve(x , y - z , y);
}
}
}
int main()
{
work();
return 0;
}
完全就是套上面那道题啦。。
代码就不贴了
BZOJ1269 [AHOI2006]文本编辑器editor
http://www.lydsy.com/JudgeOnline/problem.php?id=1269
题目都差不多,只是发现带垃圾回收的版本比不带的快好多,只要空间开足够就好。
Segment_Treap T;
void work()
{
int n , i , x , y , z , m; char str[50] , c;
scanf("%d",&m);
int pos = 0;
while (m --)
{
scanf("%s" , str);
if (*str == 'I')
{
scanf("%d",&n);getchar(); x = 0;
for (i = 1 ; i <= n ; ++ i)
{
c = getchar();
T.__insert(x , i , c);
}
T.split(T.root , y , z , pos);
T.merge(y , y , x);
T.merge(T.root , y , z);
}
if (*str == 'M')
scanf("%d",&pos);
if (*str == 'D')
{
scanf("%d",&x);
T.split(T.root , y , z , pos);
T.split(z , i , z , x);
T.merge(T.root , y , z);
}
if (*str == 'R')
{
scanf("%d",&x);
T.Reverse(pos + 1 , pos + x);
}
if (*str == 'P')
-- pos;
if (*str == 'N')
++ pos;
if (*str == 'G')
printf("%c\n" , T.query(pos + 1));
}
}
BZOJ1507: [NOI2003]Editor
样例第二条Move 16是错的,应该是Move 15
然后调了半天……然后就没什么了
Segment_Treap T;
void work()
{
int n , i , x , y , z , m; char str[50] , c;
//T.clear();
scanf("%d",&m);
int pos = 0;
while (m --)
{
scanf("%s" , str);
if (*str == 'I')
{
scanf("%d",&n);getchar(); x = 0;
for (i = 1 ; i <= n ; ++ i)
{
c = getchar(); if (c == '\n' || c == '\r') {-- i;continue;}
T.__insert(x , i , c);
}
T.split(T.root , y , z , pos);
T.merge(y , y , x);
T.merge(T.root , y , z);
}
if (*str == 'M')
scanf("%d",&pos);
if (*str == 'D')
{
scanf("%d",&x);
T.split(T.root , y , z , pos);
T.split(z , i , z , x);
//T.__delete(i);
T.merge(T.root , y , z);
}
if (*str == 'P')
-- pos;
if (*str == 'N')
++ pos;
if (*str == 'G')
{
scanf("%d",&x);
T.split(T.root , y , z , pos);
T.split(z , i , z , x);
T.__puts(i);puts("");
T.merge(z , i , z);
T.merge(T.root , y , z);
}
}
}
BZOJ1500: [NOI2005]维修数列
http://www.lydsy.com/JudgeOnline/problem.php?id=1500
本机挺快AC但是OJ疯狂TLE。。有什么强大的数据?
好吧发现splay速度是我这个Treap的3倍以上QAQ
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100005
#define M 500005
struct Segment_Treap
{
int nodecnt , root;
int key[M] ;
unsigned int priority[M] ;
int sum[M] , cnt[M];
int l[M] , r[M];
int lm[M] , rm[M] , sm[M];
int del , sz[M];
bool rev[M] , same[M];
void pushdown(int x)
{
if (rev[x])
{
if(l[x]) swap(l[l[x]] , r[l[x]]) , rev[l[x]] ^= 1 , swap(lm[l[x]] , rm[l[x]]);
if(r[x]) swap(l[r[x]] , r[r[x]]) , rev[r[x]] ^= 1 , swap(lm[r[x]] , rm[r[x]]);
rev[x] ^= 1;
}
if (same[x])
{
if(l[x]) same[l[x]] = 1 , key[l[x]] = key[x] , cnt[l[x]] = key[x] * sum[l[x]] ,
lm[l[x]] = rm[l[x]] = sm[l[x]] = max(key[x] , cnt[l[x]]);
if(r[x]) same[r[x]] = 1 , key[r[x]] = key[x] , cnt[r[x]] = key[x] * sum[r[x]] ,
lm[r[x]] = rm[r[x]] = sm[r[x]] = max(key[x] , cnt[r[x]]);
same[x] = 0;
}
}
void pushup(int x)
{
cnt[x] = key[x] , sum[x] = 1;
lm[x] = cnt[l[x]] + max(key[x] , 0), rm[x] = cnt[r[x]] + max(key[x] , 0) , sm[x] = max(lm[r[x]] , 0) + key[x] + max(rm[l[x]] , 0);
if(l[x]) lm[x] = max(lm[x] , lm[l[x]]) , rm[x] = max(rm[x] , cnt[r[x]] + key[x] + rm[l[x]]) ,
sm[x] = max(sm[x] , sm[l[x]]) , cnt[x] += cnt[l[x]] , sum[x] += sum[l[x]];
if(r[x]) rm[x] = max(rm[x] , rm[r[x]]) , lm[x] = max(lm[x] , cnt[l[x]] + key[x] + lm[r[x]]) ,
sm[x] = max(sm[x] , sm[r[x]]) , cnt[x] += cnt[r[x]] , sum[x] += sum[r[x]];
}
void __insert(int& x , int i , int k)
{
if (x)
{
pushdown(x);
if (sum[l[x]] + 1 >= i)
{
__insert(l[x] , i , k);
int y = l[x];
if (priority[y] < priority[x])
{
pushdown(y);
l[x] = r[y] , r[y] = x , x = y;
pushup(r[x]);
}
}
else
{
__insert(r[x] , i - sum[l[x]] - 1 , k);
int y = r[x];
if (priority[y] < priority[x])
{
pushdown(y);
r[x] = l[y] , l[y] = x , x = y;
pushup(l[x]);
}
}
}
else
{
if (del) x = sz[del --];else x = ++ nodecnt;
cnt[x] = key[x] = k , sum[x] = 1;
lm[x] = rm[x] = sm[x] = cnt[x];
same[x] = rev[x] = 0;
priority[x] = rand();
l[x] = r[x] = 0;
}
pushup(x);
}
void merge(int& p , int x , int y)
{
if (!x || !y) p = x | y;
else if (priority[x] < priority[y])
pushdown(x) , merge(r[x] , r[x] , y) , pushup(x) , p = x;
else pushdown(y) , merge(l[y] , x , l[y]) , pushup(y) , p = y;
}
void split(int p , int& x , int& y , int i)
{
if (!i) {x = 0 ; y = p;return;}
if (i == sum[p]) {x = p ; y = 0;return;}
pushdown(p);
if (sum[l[p]] >= i)
{
y = p;
split(l[p] , x , l[y] , i);
pushup(y);
}
else
{
x = p;
split(r[p] , r[x] , y , i - sum[l[p]] - 1);
pushup(x);
}
}
void bye(int x)
{
if(l[x]) bye(l[x]); sz[++ del] = x; if(r[x]) bye(r[x]);
}
int __query(int x , int a , int b)
{
if (a == 1 && b == sum[x]) return cnt[x];
pushdown(x);
int u = sum[l[x]] + 1;
int p = (a <= u && u <= b ? key[x] : 0);
if (a < u) p += __query(l[x] , a , b >= u ? u - 1 : b);
if (b > u) p += __query(r[x] , a <= u ? 1 : a - u , b - u);
return p;
}
};
Segment_Treap T;
int Get() {
char c=getchar(); int ret=0;
while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
if (c=='-') return -Get();
while ((c>='0')&&(c<='9')) ret=ret*10+c-'0',c=getchar();
return ret;
}
void work()
{
int n , i , j , x , y , z , m; char str[20];
n = Get() , m = Get();
for (i = 1 ; i <= n ; ++ i)
x = Get() , T.__insert(T.root , i , x);
while (m --)
{
scanf("%s" , str);
if (*str == 'I')
{
y = Get() ; n = Get(); x = 0;
for (i = 1 ; i <= n ; ++ i)
z = Get() , T.__insert(x , i , z);
T.split(T.root , j , z , y);
T.merge(j , j , x);
T.merge(T.root , j , z);
continue;
}
if (*str == 'D')
{
i = Get() ; j = Get();
T.split(T.root , x , y , i - 1);
T.split(y , y , z , j); T.bye(y);
T.merge(T.root , x , z);continue;
}
if (*(str + 2) == 'K')
{
i = Get() ; j = Get(); n = Get();
T.split(T.root , x , y , i - 1);
T.split(y , y , z , j);
T.key[y] = n , T.same[y] = 1 , T.cnt[y] = T.sum[y] * n;
T.lm[y] = T.rm[y] = T.sm[y] = max(T.cnt[y] , n);
T.merge(y , y , z);
T.merge(T.root , x , y);continue;
}
if (*str == 'R')
{
i = Get() ; j = Get();
T.split(T.root , x , y , i - 1);
T.split(y , y , z , j);
T.rev[y] ^= 1 , swap(T.l[y] , T.r[y]) , swap(T.lm[y] , T.rm[y]);
T.merge(y , y , z);
T.merge(T.root , x , y);continue;
}
if (*str == 'G')
{
i = Get() ; j = Get();
printf("%d\n" , T.__query(T.root , i , i + j - 1));continue;
}
if (*(str + 2) == 'X')
printf("%d\n" , T.sm[T.root]);
}
}
int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
work();
return 0;
}
Splay版,因为一个白痴问题调了很久……
#include
#include
#include
using namespace std;
#define N 500005
int a[N];
struct splay_tree
{
int root , nodecnt , c[N][2] , size[N] , par[N] , type[N] , stack[N];
int key[N] , sum[N] , lm[N] , rm[N] , sm[N] , same[N];
bool rev[N];
int rub[N] , rs;
void clear()
{
root = 0 , size[0] = 0;
c[0][0] = c[0][1] = par[0] = 0;
rev[0] = 0 , same[0] = 1 << 30;
nodecnt = 0;
}
int malloc(int k)
{
int x;
if (rs) x = rub[rs --]; else x = ++ nodecnt;
sum[x] = key[x] = k , size[x] = 1 , type[x] = -1;
lm[x] = rm[x] = sm[x] = key[x];
same[x] = 1 << 30 , rev[x] = 0;
c[x][0] = c[x][1] = par[x] =0;
return x;
}
void pushdown(int x)
{
if (rev[x])
{
swap(lm[x] , rm[x]) , swap(c[x][0] , c[x][1]);
if(c[x][0]) rev[c[x][0]] ^= 1 , type[c[x][0]] = 0;
if(c[x][1]) rev[c[x][1]] ^= 1 , type[c[x][1]] = 1;
rev[x] ^= 1;
}
if (same[x] != 1 << 30)
{
key[x] = same[x] , sum[x] = key[x] * size[x];
lm[x] = rm[x] = sm[x] = max(key[x] , sum[x]);
if(c[x][0]) same[c[x][0]] = same[x];
if(c[x][1]) same[c[x][1]] = same[x];
same[x] = 1 << 30;
}
}
void pushup(int x)
{
if (!x) return; pushdown(x); pushdown(c[x][0]); pushdown(c[x][1]);
sum[x] = key[x] , size[x] = 1;
lm[x] = sum[c[x][0]] + max(key[x] , 0), rm[x] = sum[c[x][1]] + max(key[x] , 0) , sm[x] = max(lm[c[x][1]] , 0) + key[x] + max(rm[c[x][0]] , 0);
if(c[x][0]) lm[x] = max(lm[x] , lm[c[x][0]]) , rm[x] = max(rm[x] , sum[c[x][1]] + key[x] + rm[c[x][0]]) ,
sm[x] = max(sm[x] , sm[c[x][0]]) , sum[x] += sum[c[x][0]] , size[x] += size[c[x][0]];
if(c[x][1]) rm[x] = max(rm[x] , rm[c[x][1]]) , lm[x] = max(lm[x] , sum[c[x][0]] + key[x] + lm[c[x][1]]) ,
sm[x] = max(sm[x] , sm[c[x][1]]) , sum[x] += sum[c[x][1]] , size[x] += size[c[x][1]];
}
void rotate (int x)
{
int t = type[x] , y = par[x] , z = c[x][t ^ 1];
type[x] = type[y] , par[x] = par[y];
if (~type[x]) c[par[x]][type[x]] = x;
type[y] = t ^ 1 , par[y] = x , c[x][t ^ 1] = y;
if (x) type[z] = t , par[z] = y;
c[y][t] = z , pushup(y);
}
void splay(int x)
{
int cnt = 0 , i; stack[++ cnt] = x;
for (i = x ; ~type[i] ; i = par[i])
stack[++ cnt] = par[i];
for (i = cnt ; i > 0 ; -- i) pushdown(stack[i]);
while (~type[x])
{
int y = par[x];
if (type[x] == type[y])rotate(y) ;else rotate(x);
if (!~type[x]) break;
rotate(x);
}
pushup(x);
}
int getKth(int x , int k)
{
while (1)
{
pushdown(x);
if (size[c[x][0]] + 1 == k) break;
if (size[c[x][0]] + 1 > k)
x = c[x][0];
else
k -= size[c[x][0]] + 1 , x = c[x][1];
}
return x;
}
void split(int p , int& x , int& y , int a)
{
if (a == size[p]) {x = p , y = 0;return;}
y = getKth(p , a + 1) , splay(y);
x = c[y][0] , type[x] = -1 , c[y][0] = 0 , par[x] = 0;
pushup(y);
}
void merge(int& p , int x ,int y)
{
if (!x || !y) {p = x | y ; return;} pushdown(x);
p = getKth(x , size[x]) , splay(p) , c[p][1] = y;
type[y] = 1 , par[y] = p , pushup(p);
}
int Build(int l , int r)
{
if (l > r) return 0;
int m = (l + r) >> 1;
int x = malloc(a[m]);
c[x][0] = Build(l , m - 1) ;if(c[x][0]) type[c[x][0]] = 0 , par[c[x][0]] = x;
c[x][1] = Build(m + 1 , r) ;if(c[x][1]) type[c[x][1]] = 1 , par[c[x][1]] = x;
pushup(x);return x;
}
void del(int x)
{
if (c[x][0]) del(c[x][0]);
rub[++ rs] = x;
if (c[x][1]) del(c[x][1]);
}
void print(int x)
{
pushdown(x);
if (c[x][0]) print(c[x][0]);
printf("%d ", key[x]);
if (c[x][1]) print(c[x][1]);
}
};
splay_tree T;
int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
int n , m , x , y , z , l , r , i; char str[20];
T.clear(); scanf("%d%d",&n,&m);
for (i = 1 ; i <= n ; ++ i)
scanf("%d",&a[i]);
T.root = T.Build(1 , n);
while (m --)
{
scanf("%s" , str);
if (*(str + 2) == 'X')
printf("%d\n" , T.sm[T.root]);
else if (*str == 'I')
{
scanf("%d%d",&l,&n);
T.split(T.root , x , y , l);
for (i = 1 ; i <= n ; ++ i)
scanf("%d",&a[i]);
z = T.Build(1 , n);
T.merge(x , x , z);
T.merge(T.root , x , y);
}
else
{
scanf("%d%d",&l,&r);
T.split(T.root , x , y , l - 1);
T.split(y , y , z , r);
if (*str == 'G') printf("%d\n" , T.sum[y]);
if (*str == 'D') T.del(y) , T.merge(T.root , x , z);
if (*str == 'M') scanf("%d",&T.same[y]);
if (*str == 'R') T.rev[y] ^= 1;
if (*str != 'D') T.merge(y , y , z) , T.merge(T.root , x , y);
}
}
return 0;
}