您的位置:首页 > 其它

【前缀和思想】cdoj1256昊昊爱运动

2015-12-07 22:19 197 查看
昊昊喜欢运动

他N天内会参加M种运动(每种运动用一个[1,m]的整数表示)

舍友有Q个问题

问昊昊第l天到第r天参加了多少种不同的运动

Input

输入两个数N, M (1≤N≤2000, 1≤M≤100);

输入N个数ai表示在第i天昊昊做了第ai类型的运动;

输入一个数Q(1≤Q≤106);

输入Q行 每行两个数 l, r(1≤l≤r≤n);

Output

一共Q行

每一行输出一个数 表示昊昊在第l天到第r天一共做了多少种活动

Sample input and output

5 3

1 2 3 2 2

3

1 4

2 4

1 5

Sample Input Sample Output

3

2

3

前缀和思想

我们去维护sum[i][j],表示[1,i]中,j究竟出现了多少次。

然后对于每一次询问,我们只要扫一遍m,判断sum[r][i]-sum[l-1][i]是否大于0就好了

这样预处理的复杂度是O(n),对于每一个询问的复杂度是O(m)

所以总体复杂度是O(n+qm)

行是运动种数,列是天数,先把读入的所有的数依次处理之后,就只需要判断首位的值是否大于0即可。如图,即为读入1 2 3 2 2的数据处理。

0 0 1 2 3 4 5

1 0 1 1 1 1 1

2 0 0 1 1 2 3

3 0 0 0 1 1 1

读入的数据每读入一个 放在相应的天的列数下,然后与前一位相加,得到这一天的判断数。c代码如下
int main(){

int n,m;

scanf("%d%d",&n,&m);

int i,j;

for(i=0;i<m;i++)sum[i][0]=0;

for(i=1;i<=n;i++){

scanf("%d",&a[i]);

sum[a[i]][i]=1;

for(j=1;j<=m;j++){

sum[j][i]+=sum[j][i-1];

}

}

int q;

scanf("%d",&q);

for(i=0;i<q;i++){

int l,r;

scanf("%d%d",&l,&r);

int num=0;

for(j=1;j<=m;j++){

if(sum[j][r]-sum[j][l-1]>0)num++;  // 判断是否出现该数,意思就是判断区间内该数的判断数是否变化,即值1 的判断数就全是11111在1 5区间内就有变化 2 4区间内无变化。

}

printf("%d\n",num);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: