文章标题 HDU 4638 : Group (莫队算法)

来源:互联网 发布:网络信息抓取 编辑:程序博客网 时间:2024/06/16 07:40

Group

题目链接
题意:有n个数的排列,然后有m个询问,然后对于连续的一段数,这些数可以作为一个分组,然后对于每次询问给定一个区间[ L,R ] ,问这个区间内有多少个组。
分析: 可以用莫队算法,对于当前已知区间[ L,R ] 的答案,我们可以O(1)去得到(L+1,R),(L-1,R),(L,R+1),(L,R-1)的答案,可以用对于当前的点 u, 如果加上他,如果flag[u-1],flag[u+1]已经在区间中,说明区间(答案)可以减1,如果flag[u-1]和flag[u+1]都没有被标记,说明加上他区间(答案)得加1,存在一个标记不改变答案;对于减去当前点 u ,则相反。
注意:就是有可能就是两个区间是不相交的,这个得特殊判断
代码:

#include<iostream>#include<string>#include<cstdio>#include<cstring>#include<vector>#include<math.h>#include<map>#include<queue> #include<algorithm>using namespace std;const int inf = 0x3f3f3f3f;typedef pair<int,int> pii;const int maxn=1e5+10;int R,L,ans;int res[maxn];struct node {    int l,r,id;}p[maxn]; int pos[maxn];//表示在第几个块 bool cmp(node a,node b){//排序     if (pos[a.l]==pos[b.l])return pos[a.r]<pos[b.r];    return pos[a.l]<pos[b.l];}int a[maxn],n,m;int flag[maxn];void add(int x){//加入一个数     if (flag[a[x]])return;    if (flag[a[x]-1]&&flag[a[x]+1])ans--;//区间减一     else if (flag[a[x]-1]==0&&flag[a[x]+1]==0)ans++;//区间加一     flag[a[x]]=1;//加上标记 }void del(int x){    if (flag[a[x]]==0)return;    if (flag[a[x]-1]&&flag[a[x]+1])ans++;//区间加一     else if (flag[a[x]-1]==0&&flag[a[x]+1]==0)ans--;//区间减一     flag[a[x]]=0;//减去标记 }int main (){    int T;    scanf ("%d",&T);    while (T--){        scanf ("%d%d",&n,&m);        memset (flag,0,sizeof (flag));        int block=sqrt(n);        for (int i=1;i<=n;i++){            scanf ("%d",&a[i]);            pos[i]=(i-1)/block+1;//得到快的位置         }        for (int i=1;i<=m;i++){            scanf ("%d%d",&p[i].l,&p[i].r);            p[i].id=i;        }        sort(p+1,p+1+m,cmp);        L=1;R=0;ans=0;        for (int i=1;i<=m;i++){            if (p[i].l>R||p[i].r<L){//区间不相交                 while (L<=R){                     flag[a[L++]]=0;                }                ans=0;                L=p[i].l;                R=p[i].l-1;                while (R<p[i].r){                    R++;                    add(R);                }                res[p[i].id]=ans;                continue;            }            while (L<p[i].l){                del(L);                L++;            }            while (L>p[i].l){                L--;                add(L);            }            while (R<p[i].r){                R++;                add(R);            }            while (R>p[i].r){                del(R);                R--;            }            res[p[i].id]=ans;        }        for (int i=1;i<=m;i++){            printf ("%d\n",res[i]);        }    }    return 0;}/*15 23 1 2 5 41 24 5*/
原创粉丝点击