[NOIP 2015] 求和
题目:洛谷P2671
难度:普及+/提高
20分(入门):
读题我们很自然就能想到一个O(n³)的算法:
枚举x,y,z,判断x,y,z组成的三元组是否合法,合法则
将其分数计入答案。
40分(入门):
原题中有这么一个式子
x<y<z,y−x=z−y
化简一下得到
y=(x+z)/2
很显然我们可以通过枚举x与z得到y,再来判断是否合法,这样我们可以将算法优化至O(n²)。
60分(普及-):
对于第5组至第6组测试数据,1≤n≤100000,1≤m≤100000,且不存在出现次数超过20的颜色
题目中的三元组有两个条件,第二个条件为
color_x=color_z
这说明虽然至多有100000个格子,至多有100000种颜色,但是由于格子x只会和一个与其颜色相同的格子z,外加一个可以计算出来的格子y结合成为三元组,所以一个格子作为x或z至多只能组成20个三元组。
由此我们可以对格子以颜色进行排序,从头开始枚举格子x,在与其相同颜色的范围内枚举格子z,并根据编号来求出y,判断是否合法。
这样可以使我们通过第5组和第6组数据。
Code:
//码风略丑
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int m,n;
long long ans;//不开long long 见祖宗
const int p=10007;
struct node{
int num,color,n;
}a[100010];
node b[100010];
int cmp(node a,node b){
return a.color<b.color;
}
int main(){
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++){
a[i].n=b[i].n=i;
scanf("%d",&a[i].num);b[i].num=a[i].num;
}
for (int