• [BZOJ 2821] 作诗


    Link:

    BZOJ 2821 传送门

    Solution:

    一道类似区间众数的经典分块

    由于个数为偶数这样的条件不能支持快速合并

    因此要先$O(n*sqrt(n))$预处理出$pre[i][j]$表示第$i$块到第$j$块的答案

    同时要建立每种颜色的有序序列方便求出一个区间内某种颜色的个数

    这样每次查询时就能$O(1)$得出整块答案,$O(size*logn)$算出非整块的数对答案的影响

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10,CNT=1505;
    vector<int> col[MAXN];
    int n,c,m,l,r,dat[MAXN],pre[CNT][CNT],block;
    int L[MAXN],R[MAXN],sub[MAXN],vis[MAXN],sum[MAXN],cnt,res;
    
    void PRE()
    {
        for(int i=1;i<=cnt;i++)
        {
            int cur=0;
            for(int j=L[i];j<=n;j++)
                sum[dat[j]]=0;
            for(int j=L[i];j<=n;j++)
            {
                if(!(sum[dat[j]]&1)&&sum[dat[j]]) cur--;
                sum[dat[j]]++;
                if(!(sum[dat[j]]&1)) cur++;
                pre[i][sub[j]]=cur;
            }
        }
        for(int i=1;i<=n;i++)
            col[dat[i]].pb(i);
        for(int i=1;i<=c;i++)
            if(col[i].size()) sort(col[i].begin(),col[i].end());
    }
    
    int cal(int x,int l,int r)
    {
        int lft=lower_bound(col[x].begin(),col[x].end(),l)-col[x].begin();
        int rgt=upper_bound(col[x].begin(),col[x].end(),r)-col[x].begin()-1;
        return max(rgt-lft+1,0);
    }
    void work(int pos,int &ret,int l,int r,int x,int y)
    {
        if(vis[dat[pos]]) return;
        int t1=cal(dat[pos],l,r),t2=cal(dat[pos],x,y);
        //注意这里的判断 
        if(!(t1&1)&&(!t2||t2&1)) ret++;
        else if((t1&1)&&!(t2&1)&&t2)ret--;
        vis[dat[pos]]=1;
    }
    int solve(int l,int r)
    {
        int bl=sub[l],br=sub[r],ret=0;
        if(bl==br||bl+1==br)
        {
            for(int i=l;i<=r;i++)
            {
                if(vis[dat[i]]) continue;
                int t=cal(dat[i],l,r);
                ret+=(!(t&1));vis[dat[i]]=1;
            }
            for(int i=l;i<=r;i++) vis[dat[i]]=0;
        }
        else
        {
            ret=pre[bl+1][br-1];
            for(int i=l;i<L[bl+1];i++)
                work(i,ret,l,r,L[bl+1],R[br-1]);
            for(int i=R[br-1]+1;i<=r;i++)
                work(i,ret,l,r,L[bl+1],R[br-1]);    
            for(int i=l;i<L[bl+1];i++) vis[dat[i]]=0;
            for(int i=R[br-1]+1;i<=r;i++) vis[dat[i]]=0;
        }
        return ret;
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&c,&m);
        block=sqrt((double)n/log((double)n)*log(2));
        cnt=n/block+(n%block!=0);
        for(int i=1;i<=n;i++) scanf("%d",&dat[i]);
        for(int i=1;i<=n;i++) sub[i]=(i-1)/block+1;
        for(int i=1;i<=cnt;i++)
            L[i]=(i-1)*block+1,R[i]=i*block;
        R[cnt]=n;PRE();
        
        while(m--)
        {
            scanf("%d%d",&l,&r);
            l=(l+res)%n+1;r=(r+res)%n+1;
            if(l>r) swap(l,r);
            printf("%d
    ",res=solve(l,r));
        }
        return 0;
    }
  • 相关阅读:
    mybatis
    spring mvc
    Spring Boot2
    Spring AOP
    Spring Boot1
    Spring IOC
    Multiple_LinearRegression_Test2
    Multiple_LinearRegression_Test
    Simple_LinearRegression_Test
    写决策树时遇到的坑
  • 原文地址:https://www.cnblogs.com/newera/p/9717523.html
Copyright © 2020-2023  润新知