bzoj 3787: Gty的文艺妹子序列

(gty妹子好多啊。。)

这个题整整调了快一天,真是累死了。。(这么神的题当然是在看某神犇博客的时候看到有这种做法,然后正好就做了233)

其实就是块套树状数组,需要维护成吨的信息,,,,

块与块之间的逆序对数,然后把每个块 i 到最后一个块 j 的逆序对和再搞到树状数组里,然后再来一个树状数组维护处到底 i 个块的时候,有多少个比 j 小的数,其实就是普通的数值插入就好了。(查询的话,块内的就用第一个树状数组求和,第二个就处理块外两部分的逆序对,然后在用第二个树状数组查分一下就可以得到块内有多少个比这个数小,或比这个数大的,答案就有了)

对于修改,一个块自己是可以暴力重构的,对于上面的2个树状数组,因为一个块修改最短引起的是全部块(根号级别)的改动(这个块和其他块的逆序对,这个块之后比..小的数)

所以每次修改的复杂度是log*根号的,每次查询的复杂度也是log*根号的,所以总的复杂度是N*logN*根号N的。

(我的天呢,这种题,,,,,,,,,,简直是无脑。。。。就是码码码码码码码   while(1) cout<<"码";)

  1 #include<bits/stdc++.h>
  2 #define N 150005
  3 #define LL long long
  4 #define inf 0x3f3f3f3f
  5 #define lowbit(x) x&(-x)   
  6 using namespace std;
  7 inline int ra()
  8 {
  9     int x=0,f=1; char ch=getchar();
 10     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
 11     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
 12     return x*f;
 13 }
 14 int sta[105],top;
 15 void writeln(int x)
 16 {    
 17     if (!x) puts("0");
 18     else{
 19     while (x){ sta[++top]=x%10; x/=10;}
 20     while (top){ putchar(sta[top]+'0'); top--;}
 21     putchar('\n');}
 22 }
 23 const int M=50005;
 24 int c[M],C[305][305],block_small[305][M];
 25 int n,m,Q,B,belong[M],sum[305],L[M],R[M],a[M],ans;
 26 void add(int x, int val){for (;x<=n;x+=lowbit(x)) c[x]+=val;}
 27 int ask(int x)
 28 {
 29     int sum=0;
 30     for (;x;x-=lowbit(x)) sum+=c[x];
 31     return sum;
 32 }
 33 
 34 void block_small_add(int pos, int x, int val){for (;x<=n;x+=lowbit(x)) block_small[pos][x]+=val;}
 35 int block_small_ask(int pos, int x)
 36 {
 37     int sum=0;
 38     for (;x;x-=lowbit(x)) sum+=block_small[pos][x];
 39     return sum;
 40 }
 41 
 42 void ADD(int pos, int x, int val){for (;x<=m;x+=lowbit(x)) C[pos][x]+=val;}
 43 int ASK(int pos, int x)
 44 {
 45     int sum=0;
 46     for (;x;x-=lowbit(x)) sum+=C[pos][x];
 47     return sum;
 48 }
 49 
 50 void pre()
 51 {
 52     for (int i=1; i<=m; i++) L[i]=(i-1)*B+1,R[i]=i*B; R[m]=n;
 53     for (int i=1; i<=m; i++)
 54     {
 55         int tot=0;
 56         for (int j=L[i]; j<=R[i]; j++)
 57             tot+=ask(n)-ask(a[j]),add(a[j],1);
 58         sum[i]=tot;
 59         for (int j=i+1; j<=m; j++)
 60         {
 61             tot=0;
 62             for (int k=L[j]; k<=R[j]; k++)
 63                 tot+=ask(n)-ask(a[k]);
 64             ADD(i,j,tot);
 65         }
 66         for (int j=L[i]; j<=R[i]; j++)
 67             add(a[j],-1);
 68     }
 69     for (int i=1; i<=m; i++)
 70     {
 71         for (int j=L[i]; j<=R[i]; j++)
 72             block_small_add(i,a[j],1);
 73         for (int j=1; j<=n; j++)
 74             block_small[i+1][j]=block_small[i][j];
 75     }
 76 }
 77 
 78 void ask(int x, int y)
 79 {
 80     ans=0;
 81     if (belong[x]==belong[y])
 82     {
 83         for (int i=x; i<=y; i++)
 84         {
 85             ans+=ask(n)-ask(a[i]);
 86             add(a[i],1);
 87         }
 88         for (int i=x; i<=y; i++) add(a[i],-1);
 89     }
 90     else
 91     {
 92         for (int i=belong[x]+1; i<belong[y]; i++)
 93             ans+=ASK(i,belong[y]-1)+sum[i];
 94         for (int i=x; i<=R[belong[x]]; i++)
 95         {
 96             ans+=ask(n)-ask(a[i]);
 97             ans+=block_small_ask(belong[y]-1,a[i]-1)-block_small_ask(belong[x],a[i]-1);
 98             add(a[i],1);
 99         }
100         for (int i=L[belong[y]]; i<=y; i++)
101         {
102             ans+=ask(n)-ask(a[i]);
103             ans+=block_small_ask(belong[y]-1,n)-block_small_ask(belong[y]-1,a[i])-block_small_ask(belong[x],n)+block_small_ask(belong[x],a[i]);
104             add(a[i],1);
105         }
106         for (int i=x; i<=R[belong[x]]; i++) add(a[i],-1);
107         for (int i=L[belong[y]]; i<=y; i++) add(a[i],-1);
108     }
109     writeln(ans);
110 }
111 
112 void change(int x, int new_val)
113 {
114     if (new_val==a[x]) return;
115     int last=0;
116     for (int i=L[belong[x]]; i<x; i++)
117     {
118         if (a[i]>a[x]) last--;
119         if (a[i]>new_val) last++;
120     }
121     for (int i=x+1; i<=R[belong[x]]; i++)
122     {
123         if (a[x]>a[i]) last--;
124         if (new_val>a[i]) last++;
125     }
126     sum[belong[x]]+=last;
127     for (int i=1; i<belong[x]; i++)
128     {
129         last=0;
130         last-=block_small_ask(i,n)-block_small_ask(i-1,n)-block_small_ask(i,a[x])+block_small_ask(i-1,a[x]);
131         last+=block_small_ask(i,n)-block_small_ask(i-1,n)-block_small_ask(i,new_val)+block_small_ask(i-1,new_val);
132         ADD(i,belong[x],last);
133     }
134     for (int i=belong[x]+1; i<=m; i++)
135     {
136         last=0;
137         last-=block_small_ask(i,a[x]-1)-block_small_ask(i-1,a[x]-1);
138         last+=block_small_ask(i,new_val-1)-block_small_ask(i-1,new_val-1);
139         ADD(belong[x],i,last);
140     }
141     for (int i=belong[x]; i<=m; i++)
142         block_small_add(i,a[x],-1),block_small_add(i,new_val,1);
143     a[x]=new_val;
144 }
145 
146 int main()
147 {
148     n=ra(); B=sqrt(n); m=n/B+(n%B!=0);
149     for (int i=1; i<=n; i++) a[i]=ra(),belong[i]=(i-1)/B+1;
150     pre();    Q=ra();
151     while (Q--)
152     {
153         int opt=ra(),x=ra()^ans,y=ra()^ans;
154         if (opt==0) { ask(x,y);}
155             else change(x,y);
156     }
157     return 0;
158 }

 

posted @ 2017-02-23 21:12  ws_ccd  阅读(285)  评论(0编辑  收藏  举报