2141: 排队 - #include <Seter> - using namespace Orz;
2141: 排队
http://www.zybbs.org/JudgeOnline/problem.php?id=2141
RunID | User | Problem | Result | Memory | Time | Language | Code Length | Submit Time |
182939 | Seter | 2141 | Accepted | 9576 kb | 1136 ms | C/Edit | 3633 B | 2011-12-27 19:09:14 |
写了N天,花了N小时各种委以后决定换方法,然后写了1小时就A了……这题的数据范围暴力居然比树套树快T^T
动态维护逆序对数目。每次交换两个数。初始逆序对数归并排序暴力乱求,然后呢?
每次交换位于i,j上的两个数后,如果这两个数一样,那么等于没交换,否则呢?
最好自己想一想……(我一开始想错了,然后调了不下5个小时,囧)
考虑哪些数与Ai,Aj的逆序关系会变。1..i-1和j+1..n肯定是没有影响的(原来在前面还是在前面)。有影响的是(假设Ai<Aj):
1.Ai,Aj,会产生一组逆序对
2.A(i+1..j-1)。这里有五种情况,可以构造出来:2 1 2 3 4 5 4,交换A1,A7,可以发现A2..6中,1和5没变,2和4各产生一组逆序对,3产生两组。
即,A(i+1..j-1)中,等于Ai或Aj的数会产生/消除一个逆序对,大小在Ai和Aj之间的数会产生/消除两个逆序对。
Ai<Aj时全部是产生逆序对,Ai>Aj时全部是消除逆序对。
于是可以树状数组/线段树套平衡树……也可以暴力找(会掉RP)……
一开始写的是每个节点记录数值外再记录一个编号,这样可以保证没有相同节点,调了N天后发生了灵异事件……
我用自己写的maker弄了个小数据出来,死循环了……于是我在自己感觉可能委掉的地方加了个putchar('!')来观察是否运行到了这个地方,另外没动,结果不死循环了……但是换一组数据又死循环……有没有神犇知道这个是神马意思!?
最后写了相同的数值合并在一个节点里,写了个手动堆,1Y……88行,也许是我写过最长的程序了吧……
#include <stdio.h> #include <string.h> #define maxn 300000 #define lt(a,b) ((a)==(b)) #define cmp(a,b) ((a)<(b)) #define icmp(a,b) ((a)<=(b)) #define scmp(a,b) ((a)>(b)) typedef struct _Splay{struct _Splay *c[2],*f;int s,v,k;}Splay,*PSplay; Splay null,st[maxn],*que[maxn],*a[20001]; char str[300000],*p=str,*o=str; int bq=-1,eq=-1,n,f[20000],b[20000],t[20000],ans; inline PSplay updt(PSplay x){return x->s=x->c[0]->s+x->c[1]->s+x->k,x;} inline PSplay near(PSplay x,_Bool c){for(x=x->c[c];x->c[!c]!=&null;x=x->c[!c]);return x;} inline PSplay extr(PSplay x,_Bool c){while(x->c[c]!=&null)x=x->c[c];return x;} inline PSplay node(v){ if(++bq==maxn)bq=0; if(!que[bq])que[bq]=st+bq; que[bq]->f=que[bq]->c[0]=que[bq]->c[1]=&null; que[bq]->k=que[bq]->s=1; que[bq]->v=v; return que[bq]; }inline PSplay rot(PSplay x){ PSplay fx=x->f,ffx=fx->f; _Bool c=fx->c[1]==x,fc=ffx->c[1]==fx; if(fx!=&null){ if((fx->c[c]=x->c[!c])!=&null)fx->c[c]->f=fx; if((x->f=ffx)!=&null)ffx->c[fc]=x; updt((fx->f=x)->c[!c]=fx); }return x; }inline PSplay splay(PSplay x,PSplay p){ if(x==&null)return x;for(;x->f!=p;rot(x))if(x->f->f!=p)rot((x->f->f->c[1]==x->f)==(x->f->c[1]==x)?x->f:x); return updt(x); }inline PSplay Join(PSplay x,PSplay y){ if(x==&null)return y;if(y==&null)return x;x=splay(extr(x,1),&null); return updt((x->c[1]=splay(y,&null))->f=x); }inline PSplay Remove(PSplay x){ if(x->k!=1)return x->k--,x->s--,x; if(++eq==maxn)eq=0;(que[eq]=x)->c[0]->f=x->c[1]->f=&null;return Join(x->c[0],x->c[1]); }inline PSplay Insert(PSplay r,int x){ _Bool c;if(!r||r==&null)return node(x); while(1){ if(lt(r->v,x))return r->k++,r->s++,splay(r,&null); if(r->c[c=cmp(r->v,x)]==&null)return splay(((r->c[c]=node(x))->f=r)->c[c],&null); r=r->c[c]; } }inline PSplay Find(PSplay*r,int x){ PSplay ans=&null,t=&null,f=(*r)->f; for(;*r!=&null;*r=t->c[cmp(t->v,x)])if(lt((t=*r)->v,x))return *r=splay(t,f); else if(icmp(t->v,x)&&(ans==&null||scmp(t->v,ans->v)))ans=t; *r=splay(ans==&null?t:ans,f);return ans; }void merge(i,j){ int c=i,mid=i+j>>1,k=mid,s=0;if(i+1==j)return;merge(i,mid);merge(mid,j); while(i!=mid){while(k!=j&&f[k]<f[i])t[s++]=f[k++];t[s++]=f[i++];ans+=k-mid;} memcpy(f+c,t,s<<2); }inline getint(){ int re=0; while(*p<'0'||*p>'9')p++; while(*p>='0'&&*p<='9')re=re*10+*p++-48; return re; }inline void BitInsert(i,x){for(i++;i<=n;i+=i&-i)a[i]=Insert(a[i],x);} inline void BitUpdate(i,x,y){for(i++;i<=n;i+=i&-i)a[i]=Remove(Find(a+i,x)),a[i]=Insert(a[i],y);} inline BitQuery(i,p,q){ int ans=0; for(i++;i;i-=i&-i){ if(Find(a+i,p)!=&null&&a[i]->v==p)ans+=a[i]->k; if(a[i]->v<=p)ans-=a[i]->c[0]->s+a[i]->k<<1; if(Find(a+i,q)!=&null&&a[i]->v==q)ans+=a[i]->k; if(a[i]->v<=q)ans+=a[i]->c[0]->s<<1; if(a[i]->v<q)ans+=a[i]->k<<1; }return ans; }inline void print(x){ char buf[11],*b=buf; if(!x)*o++=48;else{ while(x){*b++=x%10+48;x/=10;} while(b--!=buf)*o++=*b;} *o++='\n'; }main(){ int i=-1,j,t,k,x,y;_Bool d;fread(p,1,300000,stdin); null.f=null.c[0]=null.c[1]=&null; for(n=getint();++i!=n;BitInsert(i,f[i]=b[i]=getint())); merge(0,n); for(t=getint();print(ans),t--;){ if(b[i=getint()-1]==b[j=getint()-1])continue; if(i>j)i^=j^=i^=j;x=(d=b[i]<b[j])?b[i]:b[j];y=d?b[j]:b[i]; k=1;if(j-1!=i)k+=BitQuery(j-1,x,y)-BitQuery(i,x,y); ans+=d?k:-k;BitUpdate(j,b[j],k=b[i]);BitUpdate(i,k,b[i]=b[j]);b[j]=k; }*--o=0;return puts(str),0; }
2012年1月24日 22:36
这题分成sqrt(n)块来也挺快的啦。。。
2012年1月25日 14:25
每块再用平衡树等维护?恩……