zoukankan      html  css  js  c++  java
  • [BZOJ4989][Usaco2017 Feb]Why Did the Cow Cross the Road 树状数组维护逆序对

    4989: [Usaco2017 Feb]Why Did the Cow Cross the Road

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 153  Solved: 70
    [Submit][Status][Discuss]

    Description

    Why did the cow cross the road? We may never know the full reason, but it is certain that Farmer Joh
    n's cows do end up crossing the road quite frequently. In fact, they end up crossing the road so oft
    en that they often bump into each-other when their paths cross, a situation Farmer John would like t
    o remedy.Farmer John raises N breeds of cows (1≤N≤100,000), and each of his fields is dedicated to
     grazing for one specific breed; for example, a field dedicated to breed 12 can only be used for cow
    s of breed 12 and not of any other breed. A long road runs through his farm. There is a sequence of 
    NN fields on one side of the road (one for each breed), and a sequence of N fields on the other side
     of the road (also one for each breed). When a cow crosses the road, she therefore crosses between t
    he two fields designated for her specific breed.Had Farmer John planned more carefully, he would hav
    e ordered the fields by breed the same way on both sides of the road, so the two fields for each bre
    ed would be directly across the road from each-other. This would have allowed cows to cross the road
     without any cows from different breeds bumping into one-another. Alas, the orderings on both sides 
    of the road might be different, so Farmer John observes that there might be pairs of breeds that cro
    ss. A pair of different breeds (a,b) is "crossing" if any path across the road for breed aa must int
    ersect any path across the road for breed bb.Farmer John would like to minimize the number of crossi
    ng pairs of breeds. For logistical reasons, he figures he can move cows around on one side of the ro
    ad so the fields on that side undergo a "cyclic shift". That is, for some 0≤k<N, every cow re-locat
    es to the field kk fields ahead of it, with the cows in the last kk fields moving so they now popula
    te the first kk fields. For example, if the fields on one side of the road start out ordered by bree
    d as 3, 7, 1, 2, 5, 4, 6 and undergo a cyclic shift by k=2, the new order will be 4, 6, 3, 7, 1, 2, 
    5. Please determine the minimum possible number of crossing pairs of breeds that can exist after an 
    appropriate cyclic shift of the fields on one side of the road.上下有两个位置分别对应的序列A、B,长度为n,
    两序列为n的一个排列。当Ai == Bj时,上下会连一条边。
    你可以选择序列A或者序列B进行旋转任意K步,
    如 3 4 1 5 2 旋转两步为 5 2 3 4 1。
    求旋转后最小的相交的线段的对数。
     
     

    Input

    The first line of input contains N. 
    The next N lines describe the order, by breed ID, of fields on one side of the road; 
    each breed ID is an integer in the range 1…N. 
    The last N lines describe the order, by breed ID, of the fields on the other side of the road.
     

    Output

    Please output the minimum number of crossing pairs of breeds after a cyclic shift of the 
    fields on one side of the road (either side can be shifted).
     

    Sample Input

    5
    5
    4
    1
    3
    2
    1
    3
    2
    5
    4

    Sample Output

    0

    HINT

     

    Source

     
    显然题目要求求逆序对个数。
    对于每一次旋转,相当于将最后一位放到第一位。
    只有与最后一位有关的逆序对数受到影响。
    由于他从最后一位变到了第一位,原先比大的数旋转之前与他构成逆序对,旋转后不构成逆序对。反之之前比他的的数构成逆序对。统计答案即可。
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<algorithm>
     7 #define maxn 100005
     8 #define LL long long
     9 using namespace std;
    10 int n;
    11 LL a[maxn],b[maxn];
    12 LL sum[maxn];
    13 LL pos[maxn];
    14 int lowbit(int x){return x&(-x);}
    15 void update(int x,int val) {for(int i=x;i<=n;i+=lowbit(i)) sum[i]+=val;}
    16 LL query(int x){
    17     LL ans=0;
    18     for(int i=x;i>0;i-=lowbit(i)) ans+=sum[i];
    19     return ans;
    20 }
    21 int main() {
    22     scanf("%d",&n);
    23     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    24     for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
    25     for(int i=1;i<=n;i++) pos[a[i]]=i;
    26     LL cnt=0;
    27     for(int i=1;i<=n;i++) {
    28         cnt+=i-1-query(pos[b[i]]-1);
    29         update(pos[b[i]],1);
    30     }
    31     LL ans=cnt;
    32     for(int i=n;i>=1;i--) {
    33         cnt=cnt+(pos[b[i]]-1)-(n-pos[b[i]]);
    34         ans=min(ans,cnt);
    35     }
    36     memset(sum,0,sizeof(sum));
    37     for(int i=1;i<=n;i++) pos[b[i]]=i;
    38     cnt=0;
    39     for(int i=1;i<=n;i++) {
    40         cnt+=i-1-query(pos[a[i]]-1);
    41         update(pos[a[i]],1);
    42     }
    43     ans=min(cnt,ans);
    44     for(int i=n;i>=1;i--) {
    45         cnt=cnt+(pos[a[i]]-1)-(n-pos[a[i]]);
    46         ans=min(ans,cnt);
    47     }
    48     printf("%lld",ans);
    49 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    yii中的若干问题
    http请求头和响应头
    http 协议
    Jmeter -- 对并发认识的误区
    Linux top常用操作
    linux 查看系统性能
    Jmeter -- 循环控制器和线程并发(关注执行顺序)
    Jmeter -- 定时器
    性能指标:TPS 并发数 响应时间 QPS
    Jmeter -- 元件的作用域与执行顺序
  • 原文地址:https://www.cnblogs.com/wls001/p/7808058.html
Copyright © 2011-2022 走看看