zoukankan      html  css  js  c++  java
  • CF785E Anton and Permutation(分块)

    这道题本质上是一个二维数点的模板,并且是强制在线的,因此可以用树套树,但是我不会树套树

    可以想到一个暴力的方法,就是分块,分完块后,每块动态维护一个vector,因为我们发现,交换两个数后,只有在l-r区间内并且范围在a[l]-a[r]之间的数才会收到影响

    这样我们就可以通过vector查找范围

    分块这东西,还是很牛逼的,因为可以发现,每块不超过sqrt(n)并且块的数量也不超过他

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<map>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N=1e6+10;
    const int mod=1e9+7;
    vector<int> num[10005];
    int n;
    int a[N];
    int block;
    void init(){
        block=sqrt(n);
        for(int i=1;i<=n;i++){
            a[i]=i;
            int pos=(i-1)/block+1;
            num[pos].push_back(i);
        }
    }
    ll work(int l,int r){
        if(l==r)
            return 0;
        int idx1=(l-1)/block+1;
        int idx2=(r-1)/block+1;
        int x=a[l],y=a[r];
        int pos=find(num[idx1].begin(),num[idx1].end(),x)-num[idx1].begin();
        num[idx1][pos]=y;
        pos=find(num[idx2].begin(),num[idx2].end(),y)-num[idx2].begin();
        num[idx2][pos]=x;
        sort(num[idx1].begin(),num[idx1].end());
        sort(num[idx2].begin(),num[idx2].end());
        ll ans=0;
        int f;
        if(x>y){
            swap(x,y);
            f=-1;
        }
        else{
            f=1;
        }
        int i;
        if(idx1==idx2){
            for(i=l+1;i<r;i++){
                if(a[i]>x&&a[i]<y)
                    ans++;
            }
        }
        else{
            for(i=l+1;i<=idx1*block;i++)
                if(a[i]>x&&a[i]<y)
                    ans++;
            for(i=idx1+1;i<idx2;i++){
                ans+=upper_bound(num[i].begin(), num[i].end(), y) - lower_bound(num[i].begin(), num[i].end(), x);
            }
            for(i=(idx2-1)*block+1;i<r;i++)
                if(a[i]>x&&a[i]<y)
                    ans++;
        }
        swap(a[l],a[r]);
        return (2*ans+1)*f;
    }
    int main(){
        int q;
        cin>>n>>q;
        ll ans=0;
        init();
        while(q--){
            int l,r;
            cin>>l>>r;
            if(l>r)
                swap(l,r);
            ans+=work(l,r);
            cout<<ans<<endl;
        }
    }
    View Code
  • 相关阅读:
    EntityFramework系列:MySql的RowVersion
    EntityFramework系列:SQLite.CodeFirst自动生成数据库
    怎么回事呢?
    为蛇么不现实
    发布到个人主页
    作别
    budao 首页
    中午吃饱了
    作业写好了吗?
    分类
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12759051.html
Copyright © 2011-2022 走看看