hdu 4988 Little Pony and Boast Busters ( 树状数组+treap )

题意:

 给定n的两个排列, !@#¥%……&**(())*(&)+)*(&…………

http://acm.hdu.edu.cn/showproblem.php?pid=4988

思路:

先把所有数+1.....

两个排列假设是a和b,

先把a数组置换成1,2,3...n, 就是把a[i]换成i, 然后把b数组中等于a[i]的那个b[j]换成i, 然后如果只有一个询问的话就是求出b数组的逆序数。

每种交换都更新下逆序数就行了

对于第二种交换, 就是把b[i]和b[j]交换一下就行, 然后区间加加减减就可以了

对于第一种交换, 就是交换b数组里面的i和j

开一个数组记录一下on[i], 表示数i在b数组里面的下标,然后i=on[i], j=on[j], 就变成第一种交换了。


昨晚刚看了大白的uva11990 , 照着它的思路敲了下uva11990, 但是uva卡到爆, 没交上, 今天BC就来了个类似的,没搞出来可惜了。


虽然昨天刚敲了, 但是今天却完全想不到那个思路哭, 还很sb地用主席树维护, 智商捉急啊


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <cstdlib>

using namespace std;

#define inf 0x3f3f3f3f
#define LL long long
#define mxn 100020
#define ls ( p[i].ch[0] )
#define rs ( p[i].ch[1] )


struct node {
    int ch[2];
    int r, v, s;
    node() {}
    node( int v ): v( v ) {
        ch[0] = ch[1] = 0;
        r = rand();
        s = 1;
    }
}p[mxn*80];
int sz;
int creat( int v ) {
	++ sz;
	p[sz] = node( v );
	return sz;
}
int cmp( int i, int v ) {
	if( p[i].v == v )
		return -1;
	return v < p[i].v ? 0: 1;
}
void mt( int i ) {
	p[i].s = 1;
	if( ls )
		p[i].s += p[ls].s;
	if( rs )
		p[i].s += p[rs].s;
}
void rt( int &i, int d ) {
	int k = p[i].ch[d^1];
	p[i].ch[d^1] = p[k].ch[d];
	p[k].ch[d] = i;
	mt( i ), mt( k );
	i = k;
}
void insert( int &i, int v ) {
	if( !i ) {
		i = creat( v );
		return ;
	}
	int d = cmp( i, v );
	insert( p[i].ch[d], v );
	if( p[p[i].ch[d]].r > p[i].r )
		rt( i, d ^ 1 );
	mt( i );
}
void Remove( int &i, int v ) {
	int d = cmp( i, v );
	if( !~d ) {
		if( !ls )
			i = rs;
		else if( !rs )
			i = ls;
		else {
			int d2 = p[ls].r > p[rs].r ? 1: 0;
			rt( i, d2 );
			Remove( p[i].ch[d2], v );
		}
	}
	else
		Remove( p[i].ch[d], v );
	if( i )
		mt( i );
}
// 小于v的数的个数
int Low( int i, int v ) {
	if( !i )
		return 0;
	int d = cmp( i, v );
	int ret = 0;
	if( ls )
		ret += p[ls].s;
	if( !~d ) {
		return ret + 1;
	}
	if( d == 0 )
		return Low( ls, v );
	return ret + 1 + Low( rs, v );
}
// 大于v的数的个数
int Up( int i, int v ) {
	if( !i )
		return 0;
	int d = cmp( i, v );
	int ret = 0;
	if( rs )
		ret += p[rs].s;
	if( !~d )
		return ret + 1;
	if( d == 1 )
		return Up( rs, v );
	return ret + 1 + Up( ls, v );
}
int a[mxn], b[mxn], on[mxn];
int r[mxn], n;
int root[mxn];
int lb( int x ) {
    return x & -x;
}
void read() {
    for( int i = 1; i <= n; ++i ) {
        scanf( "%d", &a[i] );
        ++ a[i];
    }
    for( int i = 1; i <= n; ++i ) {
        scanf( "%d", &b[i] );
        ++ b[i];
    }
    for( int i = 1; i <= n; ++i )
        r[a[i]] = i;
    for( int i = 1; i <= n; ++i ) {
        b[i] = r[b[i]];  // 置换b数组
        on[b[i]] = i; // on[i] 表示 数i的下标
    }
}
// 更新。。
void update( int x, int v, int d ) {
    while( x <= n ) {
        if( d == -1 )
            Remove( root[x], v );
        else
            insert( root[x], v );
        x += lb( x );
    }
}
int low( int x, int v ) {
    int ret = 0;
    while( x ) {
        ret += Low( root[x], v );
        x -= lb( x );
    }
    return ret;
}
int up( int x, int v ) {
    int ret = 0;
    while( x ) {
        ret += Up( root[x], v );
        x -= lb( x );
    }
    return ret;
}
int main() {
    while( scanf( "%d", &n ) != EOF ) {
        sz = 0;
        read();
        LL ans = 0;
        memset( root, 0, sizeof( root ) );
        //  treap + 树状数组
        for( int i = 1; i <= n; ++i ) {
            for( int j = i - lb( i ) + 1; j <= i; ++j )
                insert( root[i], b[j] );
        }
        for( int i = 2; i <= n; ++i )
            ans += up( i - 1, b[i] );
        int m;
        scanf( "%d", &m );
        while( m-- ) {
            char s[10];
            scanf( "%s", s );
            if( s[0] == 'Q' ) {
                printf( "%I64d\n", ans );
                continue;
            }
            int p, x, y;
            scanf( "%d%d%d", &p, &x, &y );
            x ++, y++;
            if( x == y )
                continue;
            if( p == 0 ) {
                x = on[x], y = on[y];
            }
            if( x > y )
                swap( x, y );
            if( y - x > 1 ) {
                ans -= low( y - 1, b[x] ) - low( x, b[x] );
                ans += up( y - 1, b[x] ) - up( x, b[x] );
                ans -= up( y - 1, b[y] ) - up( x, b[y] );
                ans += low( y - 1, b[y] ) - low( x, b[y] );
            }
            if( b[x] < b[y] )
                ans ++;
            else
                ans --;
            update( x, b[x], -1 );
            update( y, b[y], -1 );
            update( x, b[y], 1 );
            update( y, b[x], 1 );
            swap( on[b[x]], on[b[y]] ); // 要先更新on数组
            swap( b[x], b[y] );
        }
    }
    return 0;
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值