zoukankan      html  css  js  c++  java
  • 洛谷 P3521 [POI2011]ROT-Tree Rotations【线段树合并】

    传送门
    这道题考察了对线段树合并的理解程度,在合并线段树的过程中就可以计算逆序对。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=2e5+10;
    int n,ls[N*50],rs[N*50],val[N*50],tot,root,rt[N*50];
    LL ans,ans1,ans2;
    struct SegTrees{
    	#define mid (l+r>>1)
    	int sum[N*50],ls[N*50],rs[N*50],tot;
    	void upd(int &id,int l,int r,int pos){
    		if(!id) id=++tot;
    		if(l==r) {sum[id]++;return;}
    		if(pos<=mid) upd(ls[id],l,mid,pos);
    		else upd(rs[id],mid+1,r,pos);
    		sum[id]=sum[ls[id]]+sum[rs[id]];
    	}
    	void merge(int &x,int y,int l,int r){
    		if(!x||!y) {x=x+y;return;}
    		if(l==r) {sum[x]+=sum[y];return;}
    		ans1+=1ll*sum[rs[x]]*sum[ls[y]];
    		ans2+=1ll*sum[rs[y]]*sum[ls[x]];
    		merge(ls[x],ls[y],l,mid);
    		merge(rs[x],rs[y],r,mid);
    		sum[x]=sum[ls[x]]+sum[rs[x]];
    	}
    	#undef mid
    }trs;
    
    void predfs(int &id){
    	id=++tot;
    	scanf("%d",&val[id]);
    	if(val[id]) return;
    	predfs(ls[id]);
    	predfs(rs[id]);
    }
    
    void dfs(int &u){
    	if(val[u]) {trs.upd(rt[u],1,n,val[u]);return;}
    	dfs(ls[u]);dfs(rs[u]);
    	ans1=ans2=0;
    	int rson=rs[u];u=ls[u];
    	trs.merge(rt[u],rt[rson],1,n);
    	ans+=min(ans1,ans2);
    }
    
    int main(){
    	scanf("%d",&n);
    	predfs(root);
    	dfs(root);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    nj07---npm
    nj06---包
    nj05---模块
    nj04---事件回调函数
    nj03---阻塞和线程
    nodejs02---demo
    nodejs简介
    【转贴】内存系列一:快速读懂内存条标签
    【转贴】4个你未必知道的内存小知识
    Linux上面mount 域控的目录 超时 然后提示 error的解决办法
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12672883.html
Copyright © 2011-2022 走看看