解题:洛谷1975 排队

题面

考虑交换两个数的影响,发现只有夹在两个数中间的大于/小于两个数的数会产生影响,而两边的状态是不变的,然后就变成了序列分块的经典问题

注意细节.jpg

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=20005,Sq=150;
 8 int a[N],uni[N],blo[N],tra[N],pts[Sq][2];
 9 int n,m,t1,t2,sqr,cnt,len,ans;
10 vector<int> v[Sq];
11 int prework()
12 {
13     sqr=sqrt(n)+10,pts[cnt=1][0]=1;
14     sort(uni+1,uni+1+n),len=unique(uni+1,uni+1+n)-uni-1;
15     for(int i=1;i<=n;i++)
16     {
17         a[i]=lower_bound(uni+1,uni+1+len,a[i])-uni;
18         blo[i]=(i-1)/sqr+1,v[blo[i]].push_back(a[i]);
19         if(i%sqr==0) pts[cnt++][1]=i,pts[cnt][0]=i+1;
20     }
21     pts[cnt][1]=n;
22     for(int i=1;i<=cnt;i++)    
23         sort(v[i].begin(),v[i].end());
24     int ret=0;
25     for(int i=1;i<=n;i++)
26     {
27         int tmp=len-a[i]+1,tep=tmp-1;
28         while(tep) ret+=tra[tep],tep-=tep&-tep;
29         while(tmp<=n) tra[tmp]++,tmp+=tmp&-tmp;
30     }
31     return ret;
32 }
33 int query(int x,int t)
34 {
35     int ret=0;
36     if(!t)
37     {
38         if(blo[t1]!=blo[t2])
39         {
40             for(int i=t1;i<=pts[blo[t1]][1];i++) ret+=(a[i]<x);
41             for(int i=pts[blo[t2]][0];i<=t2;i++) ret+=(a[i]<x); 
42             for(int i=blo[t1]+1;i<=blo[t2]-1;i++) 
43                 ret+=lower_bound(v[i].begin(),v[i].end(),x)-v[i].begin();
44          }
45         else 
46             for(int i=t1;i<=t2;i++) ret+=(a[i]<x);
47     }
48     else
49     {
50         if(blo[t1]!=blo[t2])
51         {
52             for(int i=t1;i<=pts[blo[t1]][1];i++) ret+=(a[i]>x);
53             for(int i=pts[blo[t2]][0];i<=t2;i++) ret+=(a[i]>x); 
54             for(int i=blo[t1]+1;i<=blo[t2]-1;i++) 
55                 ret+=v[i].size()-(upper_bound(v[i].begin(),v[i].end(),x)-v[i].begin());
56          }
57         else 
58             for(int i=t1;i<=t2;i++) ret+=(a[i]>x);
59     }
60     return ret;
61 }
62 void rebuild(int x,int y)
63 {
64     swap(a[x],a[y]); 
65     int b1=blo[x],b2=blo[y]; if(b1==b2) return ; 
66     v[b1].clear(),v[b2].clear(); 
67     for(int i=pts[b1][0];i<=pts[b1][1];i++)
68         v[b1].push_back(a[i]);
69     for(int i=pts[b2][0];i<=pts[b2][1];i++)
70         v[b2].push_back(a[i]);
71     sort(v[b1].begin(),v[b1].end());
72     sort(v[b2].begin(),v[b2].end());
73 }
74 int main()
75 {
76     scanf("%d",&n);
77     for(int i=1;i<=n;i++)
78         scanf("%d",&a[i]),uni[i]=a[i];
79     printf("%d
",ans=prework());
80     scanf("%d",&m);
81     while(m--)
82     {
83         scanf("%d%d",&t1,&t2);
84         if(t1>t2) swap(t1,t2);
85         int a1=a[t1],a2=a[t2];
86         if(t1!=t2-1)
87         {
88             t1++,t2--;
89             ans+=query(a1,1)-query(a1,0);
90             ans+=query(a2,0)-query(a2,1);
91             t1--,t2++;
92         }
93         if(a1<a2) ans++; if(a1>a2) ans--; 
94         rebuild(t1,t2); printf("%d
",ans);
95     }
96     return 0;
97 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9960390.html