兔子的逆序对

链接:https://ac.nowcoder.com/acm/problem/20861
来源:牛客网

题目描述

兔子最近喜欢上了逆序对。
一个逆序对(i,j) 需要满足 i < j 且 ai > aj
兔子觉得只是求一个序列的逆序对个数太没有意思了。
于是兔子想到了一个更有趣的问题!
兔子可以把区间[L,R] 反转,例如序列{1,2,3,4} 反转区间[1,3] 后是{3,2,1,4}。
兔子有m次反转操作,现在兔子想知道每次反转后逆序对个数是奇数还是偶数,兔子喜欢偶数,而讨厌奇数。
请注意,每一次反转操作都会对原序列进行改变。例如序列{1,2,3,4} 第一次操作区间[1,2] 后变成{2,1,3,4} 第二次反转区间[3,4] 后变成 {2,1,4,3}

输入描述:

第一行一个整数 n,表示序列的大小。
第二行 n 个整数ai表示序列的各个元素。

第三行一个整数m,表示操作个数。
接下来 m 行,每行两个整数 l,r,表示反转的区间。

输出描述:

输出共m行每行一个字符串,表示反转后序列逆序对个数的奇偶性,如果是逆序对个数奇数,输出"dislike"(不含引号),如果是偶数,输出"like"。

输入

4
1 2 3 4
4
1 2
3 4
1 4
2 3

输出

dislike
like
like
dislike

说明

注意:以下的(i,j)指的是位置 i 和位置 j
a={2,1,3,4} 的逆序对是 (1,2) 共1个,1是奇数,所以是dislike
a={2,1,4,3} 的逆序对是 (1,2) (3,4)共2个,2是偶数,所以是like
a={3,4,1,2} 的逆序对是 (1,3) (1,4) (2,3) (2,4)共4个,4是偶数,所以是like
a={3,1,4,2} 的逆序对是 (1,2) (1,4) (3,4) 共3个,3是奇数,所以是dislike

思路

逆序数有个性质,交换两个数的位置,奇排列变成偶排列,偶排列变成奇排列,所以每次交换后只要知道交换了几次即可。开始的逆序数可以通过树状数组求出,也可以通过归并排序算出。

树状数组:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn=1e5+10;
 6 
 7 
 8 int tree[maxn],a[maxn],n;
 9 int sum(int x)
10 {
11     int s=0;
12     while(x>0)
13     {
14         s+=tree[x];
15         x-=x&(-x);
16     }
17     return s;
18 }
19 void update(int x,int v)
20 {
21     while(x<=n)
22     {
23         tree[x]+=v;
24         x+=x&(-x);
25     }
26 }
27 int qr()
28 {
29     char c=getchar();
30     int s=0,flag=1;
31     while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
32     while(c>='0'&&c<='9'){s*=10;s+=c-'0';c=getchar();}
33     return s*flag;
34 }
35 signed main()
36 {
37     n=qr();
38     int s=0;
39     for(int i=1;i<=n;i++)
40         {
41             a[i]=qr();
42             s+=sum(a[i]);
43             update(1,1);
44             update(a[i],-1);
45         }
46     int m=qr(),flag;
47     if(s%2)
48         flag=1;
49     else
50         flag=-1;
51     for(int i=0;i<m;i++)
52     {
53         int l=qr(),r=qr();
54         if(((r-l+1)>>1)&1)
55             flag=-flag;
56         if(flag==1)
57             printf("dislike\n");
58         else
59             printf("like\n");
60     }
61     return 0;
62 }

 归并:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn=1e5+10;
 6 
 7 int a[maxn],n,sum;
 8 int qr()
 9 {
10     char c=getchar();
11     int s=0,flag=1;
12     while(c<'0'||c>'9')
13     {
14         if(c=='-')flag=-1;
15         c=getchar();
16     }
17     while(c>='0'&&c<='9')
18     {
19         s*=10;
20         s+=c-'0';
21         c=getchar();
22     }
23     return s*flag;
24 }
25 int c[maxn];
26 void Merge(int sl,int sr,int el,int er)
27 {
28     int i=sl,j=el,num=0;
29     while(i<=sr||j<=er)
30     {
31         if(i<=sr&&(a[i]<=a[j]||j>er))
32             c[num++]=a[i++];
33         else
34             c[num++]=a[j++],sum+=sr-i+1;
35     }
36     for(int k=0; k<num; k++)
37         a[sl+k]=c[k];
38 }
39 void MergeSort(int l,int r)
40 {
41     if(l<r)
42     {
43         int mid=(l+r)>>1;
44         MergeSort(l,mid);
45         MergeSort(mid+1,r);
46         Merge(l,mid,mid+1,r);
47     }
48 }
49 signed main()
50 {
51     n=qr();
52     for(int i=1; i<=n; i++)
53         a[i]=qr();
54     MergeSort(1,n);
55     int m=qr(),flag;
56     if(sum%2)
57         flag=1;
58     else
59         flag=-1;
60     for(int i=0; i<m; i++)
61     {
62         int l=qr(),r=qr();
63         if(((r-l+1)>>1)&1)
64             flag=-flag;
65         if(flag==1)
66             printf("dislike\n");
67         else
68             printf("like\n");
69     }
70     return 0;
71 }

 

posted @ 2020-09-02 00:29  一个只会爆零的小菜鸡  阅读(153)  评论(0编辑  收藏  举报