1. 程式人生 > >Codeforces 911D. Inversion Counting (數學、思維)

Codeforces 911D. Inversion Counting (數學、思維)

就會 偶數 name 一個數 space ems pan tar 題目

題目鏈接:Inversion Counting

題意:

   定義數列{ai|i=1,2,...,n}的逆序對如下:對於所有的1≤j<i≤n,若ai<aj,則<i,j>為一個逆序對。於是,對於一個數列a[1..n],給定m次操作。對於每一次操作,給定l,r(1≤l<r≤n),將序列a[l..r]倒置。求倒置後的逆序對的數量的奇偶性。

題解:

  假設現在我們有一個序列並翻轉這個序列[l,r]區間裏面的數。假設某個數的k值是指在這個值後面小於這個數的數的個數,其實我們可以發現對於[1,l-1]區間中所有的數的k值並沒有變化,同樣的對於[r+1,n]區間中的所有數的k值也沒有變化。那麽我們只用考慮[l,r]區間內k值的變化,對於[l,r]中的某個數x,那麽x的k值等於[x,r] + [r+1,n]區間小於x的數的個數,那麽後一個區間[r+1,n]的影響同樣不變,那現在我們只用只用考慮[x,r]區間對x的k值的影響了,假設沒有翻轉前[l,r]區間k值為a,則翻轉後k值為(r-l+1)*(r-l)/2 - a(可以自己驗證一下~)。所以整個序列k值相當於從 k 變到了 (r-l+1)×(r-l)/2 - a,差就為(r-l+1)×(r-l)/2 - 2×a。因為2×a是偶數,對奇偶性沒有影響,所以我們只用判斷(r-l+1)×(r-l)/2的奇偶性,如果為奇數就會改變整個序列的k值數量的奇偶性,偶數則不變。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAX_N = 3e3+9;
 4 int res[MAX_N][MAX_N];
 5 int vec[MAX_N];
 6 int main()
 7 {
 8     int N,M,T;
 9     while(cin>>N)
10     {
11         memset(res,0,sizeof(res));
12         for(int i=1;i<=N;i++)
13         {
14             scanf("
%d",&vec[i]); 15 } 16 int sum = 0; 17 for(int i=1;i<N;i++) 18 { 19 for(int j=i+1;j<=N;j++) 20 { 21 if(vec[j] < vec[i]) sum++; 22 } 23 } 24 int flag = 1; 25 if(sum%2) flag = 1; 26 else
flag = 0; 27 cin>>M; 28 for(int i=0;i<M;i++) 29 { 30 int l,r; 31 scanf("%d%d",&l,&r); 32 int x = r-l+1; 33 int t = (x*(x-1)/2)%2; 34 flag ^=t; 35 if(flag) cout<<"odd"<<endl; 36 else cout<<"even"<<endl; 37 } 38 39 } 40 return 0; 41 }

Codeforces 911D. Inversion Counting (數學、思維)