zoukankan      html  css  js  c++  java
  • LOJ#2610. 「NOIP2013」货车运输

    猜一波结论:把数组 (a,b) 排序,然后一个一个累加就是最优答案。这个结论很容易证明。

    现在问题就转换成了:给你一个数组 (b),再给你一个数组 (a),问你最少将 (a) 中相邻的数交换多少次才能将 (a,b) 中每个数的排名一一对应。注意到交换相邻的两个数,相当于冒泡排序中消除逆序对的过程,所以根据 (a) 排序后的下标对 (b) 离散化,然后树状数组求逆序对即可。

    时间复杂度 (mathcal O(nlog n))

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100000,MOD=99999997;
    struct node
    {
    	int val,pos;
    	bool operator < (const node &x) const {return val<x.val;}
    }ta[N+10],tb[N+10];
    int a[N+10],b[N+10];
    int n,c[N+10];
    int lowbit(int x) {return x&-x;}
    void modify(int x,int d)
    {
    	while(x<=n)
    	{
    		c[x]+=d;
    		x+=lowbit(x); 
    	} 
    }
    int query(int x)
    {
    	int ans=0;
    	while(x>0)
    	{
    		ans+=c[x];
    		x-=lowbit(x);
    	}
    	return ans;
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		ta[i].val=a[i];
    		ta[i].pos=i; 
    	}
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&b[i]);
    		tb[i].val=b[i];
    		tb[i].pos=i;
    	}
    	sort(ta+1,ta+n+1);
    	sort(tb+1,tb+n+1);
    //	for(int i=1;i<=n;i++) printf("%d ",ta[i].val);
    //	puts("");
    //	for(int i=1;i<=n;i++) printf("%d ",tb[i].val);
    	for(int i=1;i<=n;i++) b[ta[i].pos]=tb[i].pos;
    	int ans=0;
    	for(int i=1;i<=n;i++)
    	{
    		modify(b[i],1);
    		ans=(ans+(query(n)-query(b[i])))%MOD;
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    treap模板
    Codeforces Round #446 (Div. 2)
    BZOJ 1001: [BeiJing2006]狼抓兔子 (最小割)
    NOIP2017总结
    Python 操作 Mysql 模块
    poj 3660 Cow Contest (传递闭包)
    poj 1964 Cow Cycling(dp)
    poj 3671 Dining Cows (Dp)
    cogs 线型网络(状压dp)
    codevs 2800 送外卖(状压dp)
  • 原文地址:https://www.cnblogs.com/juruo-zzt/p/13779524.html
Copyright © 2011-2022 走看看