zoukankan      html  css  js  c++  java
  • 洛谷P1975【国家集训队】排队

    题目大意

    给出(n)个数,每次交换两个数(l,r)之后维护逆序对数量。

    题解

    初始答案用归并排序求即可。

    我们考虑交换的影响,

    显然对于区间([1,l))((r,n]),本次交换并不会对其贡献有什么影响。

    对于(l)向右移之后,在区间([l,r])中比(l)小的数的贡献消失了,新增了比(l)大的数的个数的贡献

    (r)同理。

    对于(l,r)本身,如果(l)的值大于(r),--(ans),否则++(ans)

    于是我们需要一个数据结构,支持以下操作

    区间查询比(val)小的数,

    区间查询比(val)大的数,

    单点修改。

    老规矩,线段树套平衡树即可

    献上丑陋的代码

    /*
    @Date    : 2019-07-21 10:03:17
    @Author  : Adscn (adscn@qq.com)
    @Link    : https://www.cnblogs.com/LLCSBlog
    */
    #ifdef FASTER
    #pragma GCC diagnostic error "-std=c++11"
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-fhoist-adjacent-loads")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #endif
    #include<bits/stdc++.h>
    using namespace std;
    #define IL inline
    #define RG register
    #define gi getint()
    #define gc getchar()
    #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    IL int getint()
    {
    	RG int xi=0;
    	RG char ch=gc;
    	bool f=0;
    	while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
    	while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    	return f?-xi:xi;
    }
    template<typename T>
    IL void pi(T k,char ch=0)
    {
    	if(k<0)k=-k,putchar('-');
    	if(k>=10)pi(k/10,0);
    	putchar(k%10+'0');
    	if(ch)putchar(ch);
    }
    const int N=2e4+10;
    class SplayTree{
    private:
    	struct node;
    	typedef node* tree;
    	struct node{
    		tree ch[2],par;
    		int siz,val,cnt;
    		node(void){ch[0]=ch[1]=par=NULL,cnt=val=siz=0;}
    		node(int v,tree p):par(p),val(v){ch[0]=ch[1]=NULL,cnt=siz=1;}
    	}*root;
    public:
    	SplayTree(){root=NULL;}
    	~SplayTree(){entire_free(root);}
    protected:
    	inline void entire_free(tree x)
    	{
    		if(!x)return;
    		entire_free(x->ch[0]),entire_free(x->ch[1]);
    		delete x;
    	}
    	inline bool ws(tree x,tree p){return p?p->ch[1]==x:0;}
    	inline int siz(tree x){return x?x->siz:0;}
    	inline void connect(tree x,tree p,bool which)
    	{
    		x?(x->par=p):0,
    		(p?p->ch[which]:root)=x;
    	}
    	inline void pushup(tree x){if(x)x->siz=siz(x->ch[0])+siz(x->ch[1])+x->cnt;}
    	inline void rotate(tree x)
    	{
    		tree p=x->par,g=p->par;
    		bool r=ws(x,p);
    		connect(x,g,ws(p,g)),
    		connect(x->ch[!r],p,r),
    		connect(p,x,!r);
    		pushup(p);
    	}
    	inline void Splay(tree x,tree y)
    	{
    		if(!x)return;
    		register tree p,g;
    		while(x->par!=y)
    		{
    		 	p=x->par,g=p->par;
    		 	if(g!=y)rotate(ws(x,p)^ws(p,g)?x:p);
    		 	rotate(x);
    		}
    		pushup(x);
    	}
    	inline void find(int val)
    	{
    		tree x=root;
    		while(x&&x->ch[val>x->val]&&val!=x->val)x=x->ch[val>x->val];
    //		if(x->val!=val){
    //			cerr<<"Error : FIND : val:"<<val<<" does not exist!"<<endl;
    //			return;
    //		}
    		Splay(x,NULL);
    	}
    public:
    	inline void insert(int val)
    	{
    		if(!root){
    			root=new node(val,NULL);
    			return;
    		}
    		#define nxt (val>x->val)
    		for(tree x=root;x;x=x->ch[nxt])
    		{
    			if(x->val==val)
    			{
    				++x->cnt;
    				Splay(x,NULL);
    				return;
    			}
    			if(!x->ch[nxt])
    			{
    				x->ch[nxt]=new node(val,x);
    				Splay(x->ch[nxt],NULL);
    				return;
    			}
    		}
    		#undef nxt
    		return;
    	}
    	inline void remove(int val)
    	{
    		find(val);
    		tree x=root;
    		if(!x||x->val!=val)return;
    //		cerr<<val<<endl;
    /*		try{
    			if(x==NULL)throw "empty";
    			if(x->val!=val)throw "non-existent";
    		}catch(const char *s){
    			if(s=="empty")cerr<<"Error: REMOVE : Tree is empty"<<endl;
    			if(s=="non-existent")cerr<<"Error: REMOVE : val doesn't exist"<<endl;
    			return;
    		}*/
    		if(x->cnt>1)--x->cnt;
    		else if(!x->ch[0])
    		{
    			connect(x->ch[1],NULL,0);
    			delete x;
    		}
    		else{
    			tree k=x->ch[0];
    			while(k->ch[1])k=k->ch[1];
    			Splay(k,x);
    			connect(x->ch[1],k,1);
    			connect(k,NULL,0);
    			delete x;
    		}
    	}
    	inline int rank_min(int x)
    	{
    		insert(x);
    		assert(x==root->val);
    		int ans=siz(root->ch[0]);
    		remove(x);
    		return ans;
    	}
    	inline int rank_max(int x)
    	{
    		insert(x);
    		assert(x==root->val);
    		int ans=siz(root->ch[1]);
    		remove(x);
    		return ans;
    	}
    }bt[N<<2];
    void Insert(int rt,int l,int r,int pos,int val)
    {
    	bt[rt].insert(val);
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(pos<=mid)Insert(rt<<1,l,mid,pos,val);
    	else Insert(rt<<1|1,mid+1,r,pos,val);
    }
    void Remove(int rt,int l,int r,int pos,int val)
    {
    	bt[rt].remove(val);
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(pos<=mid)Remove(rt<<1,l,mid,pos,val);
    	else Remove(rt<<1|1,mid+1,r,pos,val);
    }
    inline int Rank_min(int rt,int l,int r,int ql,int qr,int val)
    {
    	if(ql<=l&&r<=qr)return bt[rt].rank_min(val);
    	int ans=0,mid=(l+r)>>1;
    	if(ql<=mid)ans+=Rank_min(rt<<1,l,mid,ql,qr,val);
    	if(qr>mid) ans+=Rank_min(rt<<1|1,mid+1,r,ql,qr,val);
    	return ans;
    }
    inline int Rank_max(int rt,int l,int r,int ql,int qr,int val)
    {
    	if(ql<=l&&r<=qr)return bt[rt].rank_max(val);
    	int ans=0,mid=(l+r)>>1;
    	if(ql<=mid)ans+=Rank_max(rt<<1,l,mid,ql,qr,val);
    	if(qr>mid) ans+=Rank_max(rt<<1|1,mid+1,r,ql,qr,val);
    	return ans;
    }
    int c[N];
    int tmp[N],n;
    int a[N],ans;
    inline void Merge_sort(int L,int R)
    {
    	if(L==R)return;
    	int mid=(L+R)>>1;
    	Merge_sort(L,mid),Merge_sort(mid+1,R);
    	int l=L,r=mid+1,t=L;
    	while(l<=mid&&r<=R)
    	{
    		if(c[l]>c[r])ans+=mid-l+1,tmp[t++]=c[r++];
    		else tmp[t++]=c[l++];
    	}
    	while(l<=mid)tmp[t++]=c[l++];
    	while(r<=R)tmp[t++]=c[r++];
    	for(int i=L;i<=R;++i)c[i]=tmp[i];
    }
    int main(void)
    {
    	#ifndef ONLINE_JUDGE
    	File("file");
    	#endif
    	n=gi;
    	for(int i=1;i<=n;++i)c[i]=a[i]=gi,Insert(1,1,n,i,a[i]);
    	Merge_sort(1,n);
    	pi(ans,'
    ');
    	int m=gi;
    	while(m--)
    	{
    		int l=gi,r=gi;
    		if(l>r)swap(l,r);
    		ans+=Rank_max(1,1,n,l+1,r-1,a[l])-Rank_min(1,1,n,l+1,r-1,a[l]);
    		ans+=Rank_min(1,1,n,l+1,r-1,a[r])-Rank_max(1,1,n,l+1,r-1,a[r]);
    		if(a[l]>a[r])--ans;
    		if(a[l]<a[r])++ans;
    		pi(ans,'
    ');
    		Insert(1,1,n,l,a[r]);
    		Insert(1,1,n,r,a[l]);
    		Remove(1,1,n,l,a[l]);
    		Remove(1,1,n,r,a[r]);
    		swap(a[l],a[r]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    bs4抓取糗事百科
    数据结构(复习排序算法)——选泡插(选择,冒泡,插入,希尔)
    Hive-ha (十三)
    Hive优化(十一)
    Hive压缩和存储(十二)
    Hive权限管理(十)
    Hive的视图和索引(九)
    Hive动态分区和分桶(八)
    Hive(七)Hive参数操作和运行方式
    Redis 基础
  • 原文地址:https://www.cnblogs.com/LLCSBlog/p/11226667.html
Copyright © 2011-2022 走看看