spoj8406

题解:

二分+树状数组

记录以下i在当前拍第几

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int a[N],f1[N],f2[N],n,m,x,y,num[N];
int js(int x)
{
    int ans=0;
    for (;x;x-=x&-x)ans+=num[x];
    return ans;
} 
void inster(int x,int y)
{
    for (;x<=n;x+=x&-x)num[x]+=y;
}
int cmp(int x,int y)
{
    return a[x]<a[y];
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)scanf("%d",&a[i]),f1[i]=f2[i]=i;
    sort(f1+1,f1+n+1,cmp);
    for (int i=1;i<=n;i++)f2[f1[i]]=i;
    for (int i=1;i<=n;i++)inster(i,a[f1[i]]-a[f1[i-1]]);
    while (m--)
     {
         scanf("%d%d",&x,&y);
         if (x==2)
          {
             if (js(n)<y){puts("0");continue;}              
              int l=1,r=n;
              while (l<r)
               {
                   int mid=(l+r)/2;
                   if (y>js(mid))l=mid+1;
                   else r=mid;
               } 
              printf("%d
",n-l+1);           
          }
         if (x==3)
         {
             if (js(n)<y)continue;
              int l=1,r=n;
              while (l<r)
               {
                   int mid=(l+r)/2;
                   if (y>js(mid))l=mid+1;
                   else r=mid;
               } 
              inster(l,-1);             
         } 
         if (x==1)
         {
             int l=1,r=n,k=js(f2[y]);
             while (l<r)
              {
                  int mid=(l+r+1)/2;
                  if (k<js(mid))r=mid-1;
                  else l=mid;
              }
             swap(f1[f2[y]],f1[l]);
            swap(f2[f1[f2[y]]],f2[f1[l]]);
            inster(l,1);
            inster(l+1,-1); 
         } 
     }
}
原文地址:https://www.cnblogs.com/xuanyiming/p/7894531.html