Light OJ 1188

来源:互联网 发布:人工智能ai 下载 编辑:程序博客网 时间:2024/06/05 09:35

    详细:view

    题目意思特别好懂,就是找任意区间有多少个不同的数。

开始用dp做,结果MTL,后来看了提示,才会用树状数组做。

其实个人觉得题目难点就在保存出现重复的点的位置,代码中使用vis[N]记录第i个点是否重复,不重复就记为0,若重复则记录与它重复的数的位置,使用vis的目的就是用来更新树状数组的,发现vis!=0时,说明有重复元素出现,所以应该把重复的元素的位置的值减1。还有一个就是离线操作。

大致主要的思路就是这样。

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#define sf scanf#define pf printfusing namespace std;const int N=3+1e5;int vis[N],bk[N];int tree[N],a[N],ans[N],n;typedef struct node{    int idex,left;}node;vector<node> q[N];int read(int pos){    int as=0;    while(pos>0)  as+=tree[pos],pos-=pos&-pos;    return as;}void update(int pos,int val){    while(pos<=n)  tree[pos]+=val,pos+=pos&-pos;}void unit(){  memset(tree,0,sizeof(tree));  memset(bk,0,sizeof(bk));  for(int i=1;i<N;i++)    q[i].clear();}int main(){   int t,ca=0;   node tmp;   sf("%d",&t);   while(t--)   {       int qn;       sf("%d%d",&n,&qn);       unit();       for(int i=1;i<=n;i++)  sf("%d",&a[i]);       for(int i=1;i<=n;i++)  vis[i]=bk[a[i]],bk[a[i]]=i;       for(int i=1;i<=qn;i++)       {           int l,r;           sf("%d%d",&l,&r);           tmp.idex=i,tmp.left=l;           q[r].push_back(tmp);       }       //for(int i=1;i<=n;i++) pf("%d ",vis[i]);       for(int i=1;i<=n;i++)       {           if(vis[i]) update(vis[i],-1);           update(i,1);           for(int j=0;j<q[i].size();j++)           {               int tt=q[i][j].idex,l=q[i][j].left;               ans[tt]=read(i)-read(l-1);           }       }       pf("Case %d:\n",++ca);       for(int i=1;i<=qn;i++) pf("%d\n",ans[i]);   }    return 0;}


0 0