セグメントツリー


uva 11983-Weird Advertisement(スキャンライン)

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define ll long long
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
using namespace std ;

const int maxn = 611111 ;
ll sum[15][maxn<<2] ;
int cnt[maxn<<2] , f[maxn<<1] , n , k ;

struct Edge{
	int l , r , h , id ;
	bool operator < ( const Edge &p ) const{
		return h < p.h ;
	}
} edge[maxn<<1] ;

void build(int l,int r,int rt){
    cnt[rt]=0;
    sum[0][rt]=f[r+1]-f[l];
    for(int i=1;i<=k;i++)sum[i][rt]=0;
    if(l==r)return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

void push_up(int l,int r,int rt)// , 
{
	int i ;
	for ( i = 0 ; i <= k ; i ++ ) sum[i][rt] = 0 ;
	if ( cnt[rt] >= k ) sum[k][rt] = f[r+1] - f[l] ;
	else if ( l == r ) sum[cnt[rt]][rt] = f[r+1] - f[l] ;
	else{
		for ( i = k - cnt[rt] ; i <= k ; i ++ ) sum[k][rt] += sum[i][rt<<1] + sum[i][rt<<1|1] ;
		for ( i = cnt[rt] ; i < k ; i ++ ) sum[i][rt] = sum[i-cnt[rt]][rt<<1] + sum[i-cnt[rt]][rt<<1|1] ;
	}
}

void update(int L,int R,int flag,int l,int r,int rt){
    if(L<=l&&R>=r){
        cnt[rt]+=flag;
        push_up(l , r , rt);
        return;
    }
    int m=(l+r)>>1;
    if(L<=m)update(L,R,flag,lson);
    if(R>m)update(L,R,flag,rson);
    push_up(l,r,rt);
}

int main () {
	int a , b , c , d , cas , i , j , ca = 0 ;
	scanf ( "%d" , &cas ) ;
	while ( cas -- ){
		scanf ( "%d%d" , &n , &k ) ;
		int tot = 0 ;
		ll ans = 0 ;
		for ( i = 1 ; i <= n ; i ++ ){
			scanf ( "%d%d%d%d" , &a , &b , &c , &d ) ;
			c ++ , d ++ ;
			tot ++ ;
			edge[tot].l = a , edge[tot].r = c , edge[tot].h = b , edge[tot].id = 1 ;
			f[tot] = a ;
			tot ++ ;
			edge[tot].l = a , edge[tot].r = c , edge[tot].h = d , edge[tot].id = -1 ;
			f[tot] = c ;
		}
		sort ( f + 1 , f + tot + 1 ) ;
		sort ( edge + 1 , edge + tot + 1 ) ;
		int T = unique ( f + 1 , f + tot + 1 ) - f - 1 ;
		build ( 1 , T - 1 , 1 ) ;
		for ( i = 1 ; i < tot ; i ++ ){
			int l = lower_bound ( f + 1 , f + T + 1 , edge[i].l ) - f ;
			int r = lower_bound ( f + 1 , f + T + 1 , edge[i].r ) - f - 1 ;
			update ( l , r , edge[i].id , 1 , T - 1 , 1 ) ;
			ans += sum[k][1] * (ll) ( edge[i+1].h - edge[i].h ) ;
		}
		printf ( "Case %d: %lld
" , ++ ca , ans ) ; } }

1455 - Kingdom
題意:いくつかの分散した都市があり、いくつかの都市を建設しながらこれらの都市をつなぎ、同じ連通ブロックの都市では州と呼ばれている.2つの操作があり、(1)roadを1本建設し、都市a,bを接続する.(2)縦座標cの水平線がいくつかの州を通過することができ、これらの州を通過する都市は合計でいくらであるかを尋ねる.
問題の構想を解く:そして差集+線分の木、そして差集の中で保存するのは州の情報で、記録するのは州の根のノードがあって、州の縦座標の最大値と最小値、およびこの州のsize(つまりこの州はいくつかの都市を含んで、横座標は実は役に立たない).2本の線分の木を建てて、それぞれ[l,r]がどれだけの州があるか、[l,r]がどれだけの都市があるかを保存して、それでは質問する時単点の質問です(cはあなたにk*0.5であることを教えて、あなたはすべての数を2倍に拡大することができて、それではすべて整数です).road操作時に、この2つの都市が属する集合を見つけて、まずあなたの2つの都市が同じ集合にあるかどうかを見て、同じ集合にある場合は、何も操作しません.そうでなければ、この2つの集合縦座標の最値関係に基づいて区間更新を行う(これは分類して議論するが、都市の個数は少なくないが、州の個数は減少する可能性があるので、よく議論する).そして2つの都市を同じ集合にまとめます.
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
using namespace std ;

const int maxn = 1000002 ;

int sum[2][maxn<<2] , add[2][maxn<<2] ;

struct FA{
	int fa , u , d , size ;
} f[maxn] ;

int find ( int a ) { return f[a].fa = ( a == f[a].fa ? a : find ( f[a].fa ) ) ; }
int p[maxn] ;

void push_down ( int rt , int flag ){
	if ( add[flag][rt] ){
		add[flag][rt<<1] += add[flag][rt] , add[flag][rt<<1|1] += add[flag][rt] ;
		sum[flag][rt<<1] += add[flag][rt] , sum[flag][rt<<1|1] += add[flag][rt] ;
		add[flag][rt] = 0 ;
	}
}

void update ( int a , int b , int flag , int c , int l , int r , int rt ) {
	if ( a > b ) return ;
	if  ( a <= l && r <= b ){
//		printf ( "sum[%d][%d]" ) ;
		sum[flag][rt] += c ;
//    	printf ( "a = %d , b = %d , l = %d , r = %d , c = %d
" , a , b , l , r , c ) ; add[flag][rt] += c ; return ; } push_down ( rt , flag ) ; int m = ( l + r ) >> 1 ; if ( a <= m ) update ( a , b , flag , c , lson ) ; if ( m < b ) update ( a , b , flag , c , rson ) ; sum[flag][rt] = sum[flag][rt<<1|1] + sum[flag][rt<<1] ; } int query ( int a , int flag , int l , int r , int rt ){ if ( l == r ) return sum[flag][rt] ; push_down ( rt , flag ) ; int m = ( l + r ) >> 1 , ret = 0 ; if ( a <= m ) ret = query ( a , flag , lson ) ; else ret = query ( a , flag , rson ) ; return ret ; } char s[111] ; int main (){ int n , i , j , k , cas , a , b , m , l , r , x , y ; double c ; scanf ( "%d" , &cas ) ; while ( cas -- ){ scanf ( "%d" , &n ) ; for ( i = 0 ; i < n ; i ++ ) { scanf ( "%d%d", &a , &b ) ; f[i].u = f[i].d = p[i] = b * 2 ; f[i].size = 1 , f[i].fa = i ; update ( b , b , 0 , 1 , 0 , maxn - 111 , 1 ) ; update ( b , b , 1 , 1 , 0 , maxn - 111 , 1 ) ; } memset ( sum , 0 , sizeof ( sum ) ) ; memset ( add , 0 , sizeof ( add ) ) ; scanf ( "%d" , &m ) ; while ( m -- ){ scanf ( "%s" , s ) ; if ( s[0] == 'l' ){ scanf ( "%lf" , &c ) ; c *= 2 ; printf ( "%d %d
" , query ( c , 1 , 0 , maxn - 111 , 1 ) , query ( c , 0 , 0 , maxn - 111 , 1 ) ) ; } else{ scanf ( "%d%d" , &l , &r ) ; x = find ( l ) , y = find ( r ) ; if ( x == y ) continue ; int u1 = f[x].u , u2 = f[y].u , d1 = f[x].d , d2 = f[y].d ; // printf ( "%d %d %d %d %d %d
" , x , y , u1 , u2 , d1 , d2 ) ; if ( d1 > u2 ) { update ( u2 + 1 , u1 , 0 , f[y].size , 0 , maxn - 111 , 1 ) ; update ( d2 , d1 - 1 , 0 , f[x].size, 0 , maxn - 111 , 1 ) ; if ( d1 > u2 + 1 ) update ( u2 + 1 , d1 - 1 , 1 , 1 , 0 , maxn - 111 , 1 ) ; } else if ( d2 > u1 ){ update ( u1 + 1 , u2 , 0 , f[x].size , 0 , maxn - 111 , 1 ) ; update ( d1 , d2 - 1 , 0 , f[y].size, 0 , maxn - 111 , 1 ) ; if ( d2 > u1 + 1 ) update ( u1 + 1 , d2 - 1 , 1 , 1 , 0 , maxn - 111 , 1 ) ; } else if ( u2 >= d1 && u2 <= u1 ) { update ( u2 + 1 , u1 , 0 , f[y].size , 0 , maxn - 111 , 1 ) ; if ( d2 < d1 ) update ( d2 , d1 - 1 , 0 , f[x].size, 0 , maxn - 111 , 1 ) ; else update ( d1 , d2 - 1 , 0 , f[y].size , 0 , maxn - 111 , 1 ) ; // puts ( "fuck" ) ; update ( max ( d1 , d2 ) , u2 , 1 , -1 , 0 , maxn - 111 , 1 ) ; } else { update ( u1 + 1 , u2 , 0 , f[x].size , 0 , maxn - 111 , 1 ) ; if ( d1 < d2 ) update ( d1 , d2 - 1 , 0 , f[y].size, 0 , maxn - 111 , 1 ) ; else update ( d2 , d1 - 1 , 0 , f[x].size , 0 , maxn - 111 , 1 ) ; update ( max ( d1 , d2 ) , u1 , 1 , -1 , 0 , maxn - 111 , 1 ) ; } f[y].u = max ( f[y].u , f[x].u ) ; f[y].d = min ( f[y].d , f[x].d ) ; f[x].fa = y ; f[y].size += f[x].size ; // printf ( "%d %d
" , query ( 9 , 1 , 0 , maxn - 111 , 1 ) , query ( 9 , 0 , 0 , maxn - 111 , 1 ) ) ; } } } return 0 ; } /* 3 10 1 7 5 7 8 6 3 5 5 5 2 3 10 3 7 2 4 1 11 1 11 road 0 1 road 3 5 road 4 2 road 3 8 line 4.5 */