【codeforces】2014-2015ACM-ICPC CERC 14 Problem J: Pork barrel 【LCT+主席树】

来源:互联网 发布:linux内核进程调度 编辑:程序博客网 时间:2024/05/01 20:21

传送门:【codeforces】2014-2015ACM-ICPC CERC 14 Problem J: Pork barrel


题目分析:pushup内写错了一直没发现。。。把maxidx写成idx然后查了一下午没查出来,到晚饭后才发现。。然后再纠正了数组大小,终于AC了。。。写了我一下午,就因为这么一个小错误T  T


今天是平安夜,祝大家平安夜快乐!


这题是要维护一个最小生成树的构造过程。

首先,我们假设这题可以离线!

我们先将边从大到小排序,然后依次连接两点,如果某一次枚举的边的两点已经在一条链上,那么我们删除这个链上权值最大的边,然后添加这次枚举的边,这样我们既保证了连通块的数量不会增加,同时维护这么多连通块的花费也不会增加。然后我们用到了第i小的边,那么在区间中第i个位置加上这条边的权值,删除的时候就减小。

此时我们注意,当存在询问【L,R】时,如果当前枚举的边是大于等于L的最小的边,那么这时我们决定处理这个询问【L,R】。此时用到的边的最小值就是区间内【L,R】的权值和!这个我们可以用树状数组维护,且由于【1,L-1】都还没被插入,所以其实就是【1,R】内的权值和。大于R的如果是被删除的那么本来就不需要,如果是树边则只能不是用它而增加连通块个数(因为被限制只能使用权值【L,R】内的边),小于等于R的无论怎么和权值稍大且同样小于等于R的被删除的边交换,连通块个数也不会减少,因为即使没有小于等于R的限制这些边一样要删除(可能我这样描述也不太正确,抱歉T  T)。进行操作前还需要将询问按照左端点从大到小排个序。


现在问题要求强制在线,那么要么用可持久化树状数组(不知道有没有,反正我不会),要么可以用主席树(可持久化线段树)。这里我是选择主席树了。

除了用主席树保存历史记录,其他都和离线的差不多。


代码如下:


#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;typedef long long LL ;#define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )#define clr( a , x ) memset ( a , x , sizeof a )#define lson l , m#define rson m + 1 , r#define mid ( ( l + r ) >> 1 )const int MAXN = 1005 ;const int MAXE = 100005 ;const int INF = 0x3f3f3f3f ;namespace PST {struct Node {Node* c[2] ;int sum ;inline void pushup () {sum = c[0]->sum + c[1]->sum ;}} ;Node pool[MAXE * 40] ;Node* node[MAXE] ;Node* cur ;inline void init () {cur = pool ;}inline void build ( Node* &o , int l , int r ) {o = cur ++ ;o->sum = 0 ;if ( l == r ) return ;int m = mid ;build ( o->c[0] , lson ) ;build ( o->c[1] , rson ) ;}inline void insert ( Node* old , Node* &now , int x , int v , int l , int r ) {now = cur ++ ;if ( l == r ) {now->sum = old->sum + v ;return ;}int m = mid ;if ( x <= m ) {now->c[1] = old->c[1] ;insert ( old->c[0] , now->c[0] , x , v , lson ) ;} else {now->c[0] = old->c[0] ;insert ( old->c[1] , now->c[1] , x , v , rson ) ;}now->pushup () ;}inline int query ( Node* now , int x , int l , int r ) {int ans = 0 ;while ( l < r ) {int m = mid ;if ( x <= m ) {now = now->c[0] ;r = m ;} else {ans += now->c[0]->sum ;now = now->c[1] ;l = m + 1 ;}}ans += now->sum ;return ans ;}} ;namespace LCT {struct Node* null ;struct Node {Node* c[2] ;Node* f ;int flip ;int maxv , v ;int maxidx , idx ;inline void newnode ( int val , int id ) {c[0] = c[1] = f = null ;flip = 0 ;maxv = v = val ;maxidx = idx = id ;}inline void reverse () {if ( this == null ) return ;swap ( c[0] , c[1] ) ;flip ^= 1 ;}inline bool isroot () {return f == null || f->c[0] != this && f->c[1] != this ;}inline void up () {if ( this == null ) return ;maxv = v ;maxidx = idx ;if ( c[0]->maxv > maxv ) {maxv = c[0]->maxv ;maxidx = c[0]->maxidx ;}if ( c[1]->maxv > maxv ) {maxv = c[1]->maxv ;maxidx = c[1]->maxidx ;}}inline void down () {if ( this == null ) return ;if ( flip ) {c[0]->reverse () ;c[1]->reverse () ;flip = 0 ;}}inline void signdown () {if ( !isroot () ) f->signdown () ;down () ;}inline void setc ( Node* o , int d ) {c[d] = o ;o->f = this ;}inline void rot ( int d ) {Node* p = f ;Node* g = f->f ;p->setc ( c[d] , !d ) ;if ( !p->isroot () ) g->setc ( this , p == g->c[1] ) ;else f = g ;setc ( p , d ) ;p->up () ;}inline Node* splay () {signdown () ;while ( !isroot () ) {if ( f->isroot () ) rot ( this == f->c[0] ) ;else {if ( f == f->f->c[0] ) {if ( this == f->c[0] ) f->rot ( 1 ) , rot ( 1 ) ;else rot ( 0 ) , rot ( 1 ) ;} else {if ( this == f->c[1] ) f->rot ( 0 ) , rot ( 0 ) ;else rot ( 1 ) , rot ( 0 ) ;}}}up () ;return this ;}inline Node* access () {Node* o = this ;Node* x = null ;for ( ; o != null ; x = o , o = o->f ) {o->splay ()->setc ( x , 1 ) ;o->up () ;}return splay () ;}inline void makeroot () {access ()->reverse () ;}inline Node* findroot () {Node* o = access () ;for ( ; o->c[0] != null ; o = o->c[0] ) o->down () ;return o ;}inline void cut () {access () ;c[0] = c[0]->f = null ;up () ;}inline bool sameroot ( Node* o ) {return findroot () == o->findroot () ;}inline void link ( Node* o ) {//if ( this == o || sameroot ( o ) ) return ;makeroot () ;f = o ;}inline void cut ( Node* o ) {//if ( !sameroot ( o ) ) return ;makeroot () ;o->cut () ;}inline int ask ( Node* o ) {o->makeroot () ;return access ()->maxidx ;}} ;Node pool[MAXN + MAXE] ;Node* node[MAXN] ;Node* edge[MAXE] ;Node* cur ;void init () {cur = pool ;null = cur ++ ;null->newnode ( 0 , 0 ) ;}} ;struct Edge {int u , v , w ;bool operator < ( const Edge& a ) const {return w > a.w ;}} ;Edge E[MAXE] ;int a[MAXE] ;int n , m , q ;int search1 ( int x , int l , int r ) {while ( l < r ) {int m = ( l + r ) >> 1 ;if ( a[m] >= x ) r = m ;else l = m + 1 ;}return l ;}int search2 ( int x , int l , int r ) {while ( l < r ) {int m = ( l + r + 1 ) >> 1 ;if ( a[m] <= x ) l = m ;else r = m - 1 ;}return l ;}void scanf ( int& x , char c = 0 ) {while ( ( c = getchar () ) < '0' ) ;x = c - '0' ;while ( ( c = getchar () ) >= '0' ) x = x * 10 + c - '0' ;}void solve () {int l , r ;LCT :: init () ;PST :: init () ;scanf ( n ) ;scanf ( m ) ;PST :: build ( PST :: node[0] , 1 , m ) ;For ( i , 1 , m ) {scanf ( E[i].u ) ;scanf ( E[i].v ) ;scanf ( E[i].w ) ;a[i] = E[i].w ;}sort ( a + 1 , a + m + 1 ) ;sort ( E + 1 , E + m + 1 ) ;For ( i , 1 , n ) {LCT :: node[i] = LCT :: cur ++ ;LCT :: node[i]->newnode ( 0 , 0 ) ;}For ( i , 1 , m ) {LCT :: edge[i] = LCT :: cur ++ ;LCT :: edge[i]->newnode ( E[i].w , i ) ;}For ( i , 1 , m ) {int u = E[i].u ;int v = E[i].v ;PST :: insert ( PST :: node[i - 1] , PST :: node[i] , m - i + 1 , E[i].w , 1 , m ) ;if ( LCT :: node[u]->sameroot ( LCT :: node[v] ) ) {int idx = LCT :: node[u]->ask ( LCT :: node[v] ) ;LCT :: edge[idx]->cut ( LCT :: node[E[idx].u] ) ;LCT :: edge[idx]->cut ( LCT :: node[E[idx].v] ) ;PST :: insert ( PST :: node[i] , PST :: node[i] , m - idx + 1 , -E[idx].w , 1 , m ) ;}LCT :: edge[i]->link ( LCT :: node[u] ) ;LCT :: edge[i]->link ( LCT :: node[v] ) ;}int ans = 0 ;scanf ( "%d" , &q ) ;while ( q -- ) {scanf ( l ) ;scanf ( r ) ;l -= ans ;r -= ans ;l = m - search1 ( l , 1 , m ) + 1 ;r = search2 ( r , 1 , m ) ;ans = PST :: query ( PST :: node[l] , r , 1 , m ) ;printf ( "%d\n" , ans ) ;}}int main () {int T ;scanf ( T ) ;while ( T -- ) solve () ;return 0 ;}



0 0
原创粉丝点击