poj 3468 A Simple Problem with Integers

1.线段树 2700ms..

View Code
/*
Source Code

Problem: 3468 User: 314911229
Memory: 12928K Time: 2704MS
Language: G++ Result: Accepted
Source Code
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct node
{
int l, r;
long long lazy, sum;
}T[500000];

long long ans[101000];
long long sum = 0;

void insert( int l, int r, int root)
{
int mid = (l + r) / 2;
T[root].l = l, T[root].r = r;
T[root].lazy = 0;
T[root].sum = 0;
if( l == r )
{
T[root].sum = ans[l];
return;
}
insert(l, mid, root * 2);
insert(mid + 1, r, root * 2 + 1);
T[root].sum = T[root * 2].sum + T[root * 2 + 1].sum;
}

void update( int root)
{

T[root * 2].lazy += T[root].lazy;
T[root * 2 + 1].lazy += T[root].lazy;
T[root].sum += (T[root].r - T[root].l + 1) * T[root].lazy;
T[root].lazy = 0;

}

void add(int root, int a, int b,long long val)
{
int mid = (T[root].l + T[root].r) / 2;
if( T[root].l == a && T[root].r == b)
{
T[root].lazy += val;
update(root);
return;
}
if( T[root].lazy != 0)
update(root);
if( mid >= b)
add(root * 2, a, b, val);
else if( mid < a )
add(root * 2 + 1, a, b, val);
else
{
add(root * 2, a, mid, val);
add(root * 2 + 1, mid + 1, b, val);
}
if( T[root * 2].lazy != 0)
update(root * 2);
if( T[root * 2 + 1].lazy != 0)
update(root * 2 + 1);
T[root].sum = T[root * 2].sum + T[root * 2 + 1].sum;
}


void query( int a, int b, int root)
{
int mid = (T[root].l + T[root].r) / 2;
if( T[root].lazy != 0)
update(root);
if( T[root].l == a && T[root].r == b )
sum += T[root].sum ;
else
{
if( mid >= b )
query(a, b, root * 2);
else if( mid < a)
query(a, b, root * 2 + 1);
else
{
query(a, mid, root * 2);
query(mid + 1, b, root * 2 + 1);
}

}
}

int main( )
{
long long N, M, t, c;
int a, b;
char str[100];
while( scanf("%lld%lld",&N,&M) != EOF )
{
for( long long i = 1; i <= N; i++)
{
scanf("%lld",&ans[i]);
}
insert(1, N, 1);
for( long long i = 1; i <= M; i++)
{
sum = 0;
scanf("%s%d%d",str, &a, &b);
if( str[0] == 'Q' )
{
query(a, b, 1);
printf("%lld\n", sum);
}
else if( str[0] == 'C')
{
scanf("%lld",&c);
add(1, a, b, c);
}
}

}
return 0;
}
/*
5 10
1 2 3 4 5
C 1 5 2
C 2 5 2
C 1 4 2
C 2 4 -100
C 2 5 3
C 1 4 4
C 3 5 3
Q 2 4
Q 3 5
*/

注意:

1查找操作时,注意更新
2.修改操作时,最后更新sum时,要先update其孩子

 

2.伸展树,太慢,选c++编译器4700多ms

View Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


//节点定义
typedef struct node
{
node *child[2], *pf;
__int64 v, sum, lazy, id, size;
}*Node;
Node root = NULL;


inline void update( Node p )
{
if( p == NULL)
return;
else if( p->child[0] && p->child[1] )
p->sum = p->child[0]->sum + p->child[0]->lazy * p->child[0]->size + p->child[1]->sum +p->child[1]->lazy * p->child[1]->size + p->v;
else if( p->child[0])
p->sum = p->child[0]->sum + p->child[0]->lazy * p->child[0]->size + p->v;
else if( p->child[1])
p->sum = p->child[1]->sum + +p->child[1]->lazy * p->child[1]->size + p->v;
else
p->sum = p->v;
}

inline void update_size( Node p )
{
if( p == NULL)
return;
else if( p->child[0] && p->child[1] )
p->size = p->child[0]->size + p->child[1]->size + 1;
else if( p->child[0])
p->size = p->child[0]->size + 1;
else if( p->child[1])
p->size = p->child[1]->size + 1;
else
p->size = 1;
}


inline void update_lazy( Node p)
{

if( p == NULL)
return;
p->sum += p->size * p->lazy;
if( p->child[0] && p->child[1] )
{
p->child[0]->lazy += p->lazy;
p->child[1]->lazy += p->lazy;
p->v += p->lazy;
p->lazy = 0;
}
else if( p->child[0])
{
p->child[0]->lazy += p->lazy;
p->v += p->lazy;
p->lazy = 0;
}
else if( p->child[1])
{
p->child[1]->lazy += p->lazy;
p->v += p->lazy;
p->lazy = 0;
}
else
{
p->v += p->lazy;
p->lazy = 0;
}
}

//左孩子0,右孩子1
inline void Rotate(Node p, __int64 x)
{
Node q = p->child[x];
update_lazy( p );
update_lazy( q );
p->child[x] = q->child[!x];
if( q->child[!x] )
q->child[!x]->pf = p;
q->child[!x] = p;
if( p->pf )
{
if( p->pf->child[x] == p)
p->pf->child[x] = q;
else
p->pf->child[!x] = q;
}
q->pf = p->pf;
if( p->pf == NULL )
root = q;
p->pf = q;
q->sum = p->sum;
update(p);
q->size = p->size;
update_size( p );
}

inline void splay( Node p, Node q)
{
while( p->pf != q )
{
Node p1 = p->pf;
if( p1->pf == q )
{
if(p1->child[0] == p)
Rotate(p1, 0);
else
Rotate(p1, 1);
}
else if( p1->pf->child[0] == p1 )
{
if( p1->child[0] == p )
{
Rotate(p1->pf, 0);
Rotate(p1, 0);
}
else
{

Rotate(p1,1);
Rotate(p->pf,0);
}
}
else if( p1->pf->child[1] == p1 )
{
if( p1->child[1] == p )
{
Rotate(p1->pf, 1);
Rotate(p1, 1);
}
else
{

Rotate(p1, 0);
Rotate(p->pf, 1);
}
}
}
}

void insert(Node &p, Node q, Node father)
{
if( p == NULL )
{
p = q;
p->pf = father;
splay(p,NULL);
return;
}
if( p->id > q->id )
insert(p->child[0], q, p);
else
insert(p->child[1], q, p);
update(p);
update_size(p);
}


Node NewNode(__int64 idx, __int64 t)
{
Node q = new node;
q->child[0] = NULL;
q->child[1] = NULL;
q->pf = NULL;
q->v = t;
q->lazy = 0;
q->sum = 0;
q->size = 1;
q->id = idx;
return q;
}

Node splay_find(Node p, __int64 x )
{
if( p->id == x )
return p;
if( p->id > x )
{
update_lazy( p );
return splay_find(p->child[0], x);
}
else
{
update_lazy( p );
return splay_find(p->child[1], x);
}
}

__int64 splay_sum( Node p)
{
return p->sum + p->size * p->lazy;
}


__int64 query( __int64 a, __int64 b)
{
Node p1 = splay_find(root, a - 1);
Node p2 = splay_find(root, b + 1);
splay(p1, NULL);
splay(p2, p1 );
if( root->child[1]->child[0] )
{
return splay_sum(root->child[1]->child[0]);
}
return 0;
}
int main( )
{
__int64 N, M, t, a, b, c;
char str[100];
while( scanf("%I64d%I64d",&N,&M) != EOF )
{
Node q;
root = NULL;
q = NewNode(0, 0);
insert(root, q, NULL);
for( __int64 i = 1; i <= N; i++)
{
scanf("%I64d",&t);
q = NewNode(i, t );
insert(root, q, NULL);
}
q = NewNode(N + 1, 0);
insert(root, q, NULL);
for( __int64 i = 1; i <= M; i++)
{
scanf("%s%I64d%I64d",str, &a, &b);
if( str[0] == 'Q' )
printf("%I64d\n", query(a, b));
else if( str[0] == 'C')
{
scanf("%I64d",&c);
Node p1 = splay_find(root, a - 1);
Node p2 = splay_find(root, b + 1);
splay(p1, NULL);
splay(p2, p1 );
if( root->child[1]->child[0] )
{
root->child[1]->child[0]->lazy += c;
}
}

}

}
return 0;
}

需要维护信息有size, lazy, sum,

旋转是要push_down(p),push_down(q)

将lazy往其孩子传递。

更新sum值时,也要注意

 

3.树状数组,1157ms,orz...强大啊

详细讲解

http://blog.csdn.net/tsaid/article/details/6740795

View Code
/*
Source Code

Problem: 3468 User: 314911229
Memory: 3300K Time: 1157MS
Language: C++ Result: Accepted
Source Code
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN 100005
long long ans[100010];
long long dt[100010];
long long delta[100010];
long long diysum[100010];

int lowbit( int x)
{
return x&-x;
}

void add( int x, long long val, long long *dx)
{
while( x < MAXN )
{
dx[x] += val;
x += lowbit(x);
}
}

long long sum( long long x, long long *dx)
{
long long sumt = 0;
while( x )
{
sumt += dx[x];
x -= lowbit(x);
}
return sumt;
}

int main( )
{
long long N, M, t, c;
int a, b;
char str[100];
while( scanf("%lld%lld",&N,&M) != EOF )
{
memset(ans, 0, sizeof(ans));
memset(delta, 0, sizeof(delta));
memset(dt, 0, sizeof(dt));
memset(diysum, 0, sizeof(diysum));
for( long long i = 1; i <= N; i++)
{
scanf("%lld",&t);
add(i, t, ans);
}
for(long long i = 1; i <= M; i++)
{

scanf("%s%d%d",str, &a, &b);
if( str[0] == 'Q' )
{
long long s1 = sum(a-1, ans);
long long s2 = sum( b , ans);
long long s3 = sum(a - 1, delta);
long long s0 = sum(b, delta);
long long s4 = (b + 1) * s0 - a * s3;
long long s5 = sum(b, diysum);
long long s6 = sum(a-1,diysum);
s5 = s5 - s6;
printf("%lld\n",s2 - s1 + s4 - s5);
}
else if( str[0] == 'C')
{
scanf("%lld",&c);
long long temp1 = dt[a];
long long temp2 = dt[b + 1];
dt[a] += c;
dt[b + 1] += -c;
add(a, c, delta);
add(b + 1, -c, delta);
long long cnt1 = a * ( dt[a] - temp1);
long long cnt2 = (b + 1) * ( dt[b + 1] - temp2);
add(a,cnt1, diysum);
add(b + 1, cnt2, diysum);
}
}

}
return 0;
}

/*
5 10
1 2 3 4 5
C 1 5 2
C 2 5 2
C 1 4 2
C 2 4 -100
C 2 5 3
C 1 4 4
C 3 5 3
Q 2 4
Q 3 5
*/



posted on 2012-03-06 13:24  more think, more gains  阅读(212)  评论(0编辑  收藏  举报

导航