颜色

来源:互联网 发布:英制螺纹如何编程 编辑:程序博客网 时间:2024/03/29 05:48


问题 G: 颜色

时间限制: 4 Sec  内存限制: 512 MB、

题目描述

给定一个长度为N的颜色序列C,对于该序列中的任意一个元素Ci,都有1<=Ci<=M。对于一种颜色ColorK来说,区间[L,R]内的权值定义为这种颜色在该区间中出现的次数的平方,即区间[L,R]内中满足Ci=ColorK的元素个数的平方。接下来给出Q个询问,询问区间[L,R]内颜色[a,b]的权值总和。
 

输入

第1行三个整数N,M,Q。分别代表序列长度,颜色总数和询问总数。
第2行N个整数,代表序列Ci。
第3行到第Q+2行,每行4个整数l,r,a,b。记上一次计算出的答案为Lans。那么实际的l,r,a,b为给出的l,r,a,b xor上Lans。第一个询问的时候Lans=0。
 

输出

总共Q行,对于每一个询问,输出权值总和

样例输入

4 2 31 1 2 2 1 4 1 210 11 9 103 0 0 0

样例输出

820

提示






1<=N,Q<=50000,M<=20000 


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#define V 50005
//#define LL long long 
using namespace std;
int n,blo,id,m;
int v[V],bl[V],s[V];//,ps[V]
map<int,int>ma;
int f[250][20003],g[20003];
inline void pre(int x)
{
   for(int i=1;i<=m;i++)
   {
     f[x][i]+=f[x-1][i];
   }

inline int query(int l,int r,int a,int b)
{
     int ans=0;
     memset(g,0,sizeof(g));
     for(int i=l;i<=min(bl[l]*blo,r);i++)
     g[v[i]]++;
     if(bl[l]!=bl[r])
       for(int i=(bl[r]-1)*blo+1;i<=r;i++)
       g[v[i]]++;
     if(bl[l]<bl[r]-1)
     {
      for(int i=a;i<=b;i++)
      {
      g[i]+=f[bl[r]-1][i]-f[bl[l]][i];
        ans+=g[i]*g[i];
      }
     }
     else
     {
      for(int i=a;i<=b;i++)
      ans+=g[i]*g[i];
     }
    // z+=f[bl[r]-1][h]-f[bl[l]][h];
    // ans+=z*z;
     return ans;   
}
int main()
{
 //  freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
   //freopen("ACautomata.in","r",stdin);freopen("ACautomata.out","w",stdout);
    int q;
    scanf("%d%d%d",&n,&m,&q);
    blo=sqrt(n);
    for(int i=1;i<=n;i++)
    {
          scanf("%d",&s[i]);
          v[i]=s[i];
    }
    sort(s+1,s+n+1);
    for(int i=1;i<=n;i++)
    if(!ma[s[i]])
    ma[s[i]]=++id;              
     for(int i=1;i<=n;i++)       
       v[i]=ma[v[i]];
    for(int i=1;i<=n;i++)
    {
      bl[i]=(i-1)/blo+1;
      f[bl[i]][v[i]]++;
    }
    
    for(int i=1;i<=bl[n];i++)
    {
     pre(i);
    }      
    int l,r,a,b,x=1,y=n;
    int zz=0;
    int aa,bb;
    for(int i=1;i<=q;i++)
    {
          scanf("%d%d%d%d",&l,&r,&a,&b);
          l^=zz;
          r^=zz;
          a^=zz;
          b^=zz;
          if(a>s[n]&&b>s[n])
          {
            zz=0;
            printf("%lld\n",zz);
            continue;
          }
          aa=lower_bound(s+1,s+n+1,a)-(s);
          bb=lower_bound(s+1,s+n+1,b)-(s);//lower_bound(ve[i]+1,ve[i]+pp+1,x)-(ve[i]+1)
          a=ma[s[aa]];
          b=ma[s[bb]];
          if(a>b)
          {
            swap(a,b); 
          }
          if(l>r)swap(l,r);
          l=max(l,x);
          r=min(y,r);
          if(a>m)
          {
           zz=0;     
           printf("%d\n",zz);   
           continue;   
          }
          zz=query(l,r,a,b);
          printf("%d\n",zz);
    }
    return 0;    
}