HDU 5193 块状链表求带插入删除操作的全局逆序对数
2017-08-05 22:07
441 查看
#include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define maxn 20010 #define maxlim 150 using namespace std; inline void read(int &x) { char ch; bool flag = false; for (ch = getchar(); !isdigit(ch); ch = getchar())if (ch == '-') flag = true; for (x = 0; isdigit(ch); x = x * 10 + ch - '0', ch = getchar()); x = flag ? -x : x; } inline void write(int x) { static const int maxlen = 100; static char s[maxlen]; if (x < 0) { putchar('-'); x = -x;} if (!x) { putchar('0'); return; } int len = 0; for (; x; x /= 10) s[len++] = x % 10 + '0'; for (int i = len - 1; i >= 0; --i) putchar(s[i]); } int lim; int block[2*maxlim][2*maxlim]; int siz[maxlim] , cnt; int pree[2*maxlim],nextt[2*maxlim]; int n,m; int tree[2*maxlim][maxn]; int ans=0; int get_pos(int &x){ int now=1; while ( ( siz[now]<x) && ( nextt[now] ) ) { x-=siz[now]; now=nextt[now]; } return now; } int lowbit(int x){ return x & (-x); } void add(int pos,int x,int op){ while (x<=n) { tree[pos][x]+=op; x+=lowbit(x); } } int query(int pos,int x){ int tmp=0; while (x) { tmp+=tree[pos][x]; x-=lowbit(x); } return tmp; } void build(int a,int b){ pree[b]=a; nextt[a]=b; } void rebuild(int x){ memset(tree[x],0,sizeof (tree[x])); for (int i=1;i<=siz[x];i++) add( x , block[x][i] ,1); } void calc(int at_block,int v,int at_in,int op){ int tmp=at_block; while ( pree[tmp] ) { tmp=pree[tmp]; ans+=( siz[tmp]-query(tmp,v) )*op; } tmp=at_block; while ( nextt[tmp] ) { tmp=nextt[tmp]; ans+=query( tmp ,v-1 )*op; } for (int i=1;i<=at_in;i++) if (block[ at_block ][i]>v) ans+=op; for (int i=at_in+1;i<=siz[ at_block ];i++) if (block[ at_block ][i]<v) ans+=op; } void watch(){ for (int i=1;i;i=nextt[i]) { printf("val= "); for (int j=1;j<=siz[ i ];j++) printf(" %d ",block[i][j] ); puts(""); } } void ins(int pos,int v){ int at_block=get_pos(pos); calc(at_block,v,pos,1); add(at_block , v ,1); memmove(block[at_block]+pos+2,block[at_block]+pos+1, sizeof(int)*(siz[ at_block ]-pos) ); block[ at_block ][ pos+1 ]=v; siz[ at_block ]++; if (siz[at_block]>=2*lim) { ++cnt; build(cnt,nextt[at_block ] ); build(at_block ,cnt); siz[cnt]=lim; siz[at_block]=lim; memcpy(block[cnt]+1,block[at_block]+lim+1,sizeof(int)*lim); rebuild(at_block ); rebuild(cnt); } } void Delete(int pos){ int at_block=get_pos(pos); calc(at_block, block[ at_block ][ pos ] ,pos,-1); add(at_block, block[ at_block ][ pos ] ,-1); memmove(block[at_block]+pos,block[at_block ]+pos+1, sizeof(int)*(siz[at_block]-pos) ); siz[ at_block ]--; if (siz[at_block]==0) { if (at_block!=1) build(pree[at_block],nextt[at_block]); } } int main(){ while (scanf("%d%d",&n,&m)!=EOF) { cnt=1; pree[1]=0; nextt[1]=0; siz[1]=0; lim=sqrt(n); ans=0; for (int i=1;i<=n;i++) { int x; read(x); ins( i-1 , x); } for (int i=1;i<=m;i++) { int op; read(op); if (op==0) { int x,pos; read(pos); read(x); ins(pos,x); printf("%d\n",ans); } else { int x; read(x); Delete(x); printf("%d\n",ans); } } } return 0; }
相关文章推荐
- HDU 5193 Go to movies Ⅱ 块状链表套树状数组(带插入和删除的逆序对)
- hdu_5193_Go to movies Ⅱ(带插入删除的逆序对,块状链表)
- Hdu 5193 Go to movies Ⅱ(带删除数插入数的逆序数对,块状链表)
- 2016年12月21日学习总结----单向循环链表操作程序(头插,尾插,中间插入,删除,逆序)
- 单链表的基本操作,正序/逆序建表(尾插法/头插法)、计算单链表长度、输出单链表内容、插入、删除,给出完整代码
- 数据结构:链表的基本操作(创建,删除,插入,逆序,摧毁)
- 链表操作总结-包括链表合并、插入删除、清空复制、逆序
- 学习笔记——C语言实现单链表的基本操作:创建、输出、插入结点、删除结点、逆序链表
- C语言实现双向链表删除节点、插入节点、双向输出等操作
- 链表面试题(一):逆序打印链表、无头链表删除插入节点、约瑟夫环、逆置单链表
- (C语言版)链表(一)——实现单向链表创建、插入、删除等简单操作(包含个人理解说明及注释,新手跟着写代码)
- (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作
- (C语言版)链表(四)——实现双向循环链表创建、插入、删除、释放内存等简单操作
- 链表的一些基本操作:动态链表、插入和删除等
- c++中对单链表操作---合并两个链表&&单链表逆序&&删除链表中的中间结点
- 数据结构:单链表(二)之链表节点排序,升序插入数据,删除指定的所有节点,翻转链表操作
- 用JAVA语言,编写一个链表类(双向链表),实现插入,删除,查找操作
- (C++版)链表(四)——实现双向循环链表创建、插入、删除等简单操作
- 链表(1)基本操作:创建,插入,删除,销毁等(模板类实现)
- 数据结构链表的操作集合(建立,遍历,插入,删除,排序,长度,空判断等)