URAL 2080 莫队

题意 有m种卡 给出卡的使用序列 要求每次从卡堆的顶部抽一张出来 刚好符合序列 输出初始 卡堆的排序 再输出每次抽出卡用后 卡插回卡堆的时候 这张卡上面有几张卡

初始排序很容易就可以搞出来 但是需要注意的是 如果我有三种卡 而我只用了第一种 在输出卡堆里 仍然要输出没有用到的2和3 

可以想到 既然每张卡都只有一种 那么 由这种规则来看 如果一张卡被抽出之后 接下来还要用 它插回去的位置上面 必须有在这个过程之中 要用的别的卡 很容易的就想到 插回去 上面有几张卡 取决于这次用这张卡和下次用这张卡之间有几种卡 有一种 插回去的位置上面就有几个 如果用了这张卡之后不会再用到了 那就无脑的插到卡堆的最下 即m-1

关于一张卡的两个相邻使用位置 用莫队来搞就好 n是1e5 抽象出来的询问也不到1e5 复杂度还是过的去的 需要注意的是 询问id是该询问的L

其实如果想到了插回取决于什么..就是一道莫队水题了..然而被初始卡堆的输出trick到了..orz 我的绝杀...

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
#include<math.h>
using namespace std;
struct node
{
    int l,r,id;
};
int q[100050];
int a[100050];
int pl[100050];
int ans[100050];
node xw[100050];
int pos[100050];
vector<int >v[100050];
int cmp(node a,node b)
{
    if(pos[a.l]==pos[b.l])
        return a.r<b.r;
    return a.l<b.l;
}
int an;
void add(int x)
{
    int z = a[x];
    if(q[z]==0)
        an++;
    q[z]++;
}
void del(int x)
{
    int z= a[x];
    if(q[z]==1)
        an--;
    q[z]--;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&m,&n))
    {
        for(int i=1; i<=m; i++)q[i]=0;
        for(int i=1; i<=m; i++)
            v[i].clear();
        int sz=sqrt(n);
        for(int i =1; i<=n; i++)
            scanf("%d",&a[i]);
        int cnt = 0;
        for(int i =1; i<=n; i++)
        {
            pos[i]=i/sz;
            v[a[i]].push_back(i);
            if(q[a[i]]==0)
            {
                pl[++cnt]=a[i];
                q[a[i]]++;
            }
        }
        for(int i = 1; i<= m ;i++)
        {
            if(q[i]==0)
            {
                pl[++cnt]=i;
                q[i]++;
            }
        }
        int res=0;
        for(int i=1; i<=m; i++)
        {
            int siz=v[i].size();
            for(int j=0; j<siz; j++)
            {
                if(j+1==siz)
                {
                    xw[++res].l=-1;
                    xw[res].r=-1;
                }
                else
                {
                    xw[++res].l=v[i][j];
                    xw[res].r=v[i][j+1];
                }
                xw[res].id=v[i][j];
            }
        }
        sort(xw+1,xw+1+n,cmp);
        int l = 1;
        int r = 0;
        an = 0;
        for(int i=1; i<=m; i++)q[i]=0;
        for(int i = 1; i<=n; i++)
        {
            if(xw[i].l==-1)
            {
                ans[xw[i].id]=m-1;
                continue;
            }
            while(l<xw[i].l)
            {
                del(l);
                l++;
            }
            while(l>xw[i].l)
            {
                l--;
                add(l);
            }
            while(r>xw[i].r)
            {
                del(r);
                r--;
            }
            while(r<xw[i].r)
            {
                r++;
                add(r);
            }
            ans[xw[i].id]=an-1;
        }
        for(int i = 1; i<=cnt; i++)
        {
            printf("%d",pl[i]);
            if(i==cnt)
                printf("
");
            else printf(" ");
        }
        for(int i = 1; i<=n; i++)
        {
            printf("%d
",ans[i]);
        }
    }
}

  

原文地址:https://www.cnblogs.com/rayrayrainrain/p/5774595.html