A. AquaMoon and Strange Sort
叉人題
如果數字各不相同,只需要統計每個數參與構成的逆序對總數,如果是奇數一定最終朝左,偶數朝右。無意義的數字交換對方向是沒有影響的
繼續考慮相同數字帶來的影響。逆序對考慮的交換次數是最小交換,是保守排序,相同數字的相對位置不變。把交換次數的序列按奇偶提取出來,比如001110 001100。每次操作交換兩個數字然後把它翻轉,那麼只有對相同的相鄰數進行操作纔有意義。
模型轉化爲給一個01序列,每次選擇兩個相鄰的相同數,把它們翻轉,問最後能否化成全0序列。
100100也是可行的。100100->111111->000000
把序列想象成多個連續的01段拼接。偶數段是可以任意轉化的,對答案不產生影響,能把左右直接相連。奇數段則不行,需要把它壓成一個數。用棧來考慮這個問題,如果是偶數段,什麼也不插入,如果是奇數段,會插入一個0/1,如果棧尾和新插入的元素相同,說明能合併,如果不同就推進棧尾。在最終的棧中,如果棧空或者只有一個0,則合法,其他情況我們處理不掉1,均不合法。
1 #include <vector> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=1e5, N1=maxn+5; 8 9 template <typename _T> void read(_T &ret) 10 { 11 ret=0; _T fh=1; char c=getchar(); 12 while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); } 13 while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); } 14 ret=ret*fh; 15 } 16 17 int n,T,ma; 18 int a[N1],num[N1]; 19 vector<int>to[N1]; 20 int stk[N1],tp; 21 22 struct BIT{ 23 int sum[N1]; 24 void upd(int x,int w){ for(int i=x;i<=ma;i+=i&(-i)) sum[i]+=w; } 25 int query(int x){ int ans=0; for(int i=x;i;i-=i&(-i)) ans+=sum[i]; return ans; } 26 void clr(){ for(int i=0;i<=ma;i++) sum[i]=0; } 27 }s; 28 29 int main() 30 { 31 // freopen("a.in","r",stdin); 32 scanf("%d",&T); 33 while(T--){ 34 35 scanf("%d",&n); ma=0; 36 for(int i=1;i<=n;i++) read(a[i]), ma=max(a[i],ma); 37 for(int i=1;i<=n;i++) 38 { 39 num[i]=s.query(ma)-s.query(a[i]); 40 s.upd(a[i],1); 41 } 42 s.clr(); 43 for(int i=n;i>=1;i--) 44 { 45 num[i]+=s.query(a[i]-1); 46 s.upd(a[i],1); 47 to[a[i]].push_back(num[i]&1); 48 } 49 s.clr(); 50 int fl=1; 51 for(int k=1;k<=ma;k++) 52 { 53 tp=0; 54 for(int i=0,j;i<to[k].size();) 55 { 56 for(j=i;j<to[k].size() && to[k][j]==to[k][i];j++); 57 if((j-i)&1) 58 { 59 if(!tp) stk[++tp]=to[k][i]; 60 else if(stk[tp]==to[k][i]) tp--; 61 else stk[++tp]=to[k][i]; 62 } 63 i=j; 64 } 65 if(tp>1||(tp==1&&stk[tp]==1)) fl=0; 66 to[k].clear(); tp=0; 67 } 68 puts(fl?"YES":"NO"); 69 70 } 71 return 0; 72 }