NBUT 1457 是要求区间内不同的数出现次数的立方和
CodeForces 220B 是要求区间内不同的数出现次数等于其本身个数和。
由于两题给的数都是 1 ~ 1e9, 而且n的范围是1 ~ 1e5, 所以都需要离散化一下。这两题也就十分相似。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define ll __int64
using namespace std;
const int N = 100103;
int n, m, pos[N];
int c[N], sub[N] ;
ll s[N], ans;
inline ll cube(ll x) {
return x*x*x;
}
struct node {
int l, r, id;
ll ans;
}q[N];
bool cmp(node a, node b) {
if(pos[a.l] == pos[b.l]) {
return a.r < b.r;
}
return a.l < b.l;
}
bool cmpId(node a, node b) {
return a.id < b.id;
}
inline void scanf_(int &num) {
char in;
bool neg=false;
while(((in=getchar()) > '9' || in<'0') && in!='-') ;
if(in=='-') {
neg=true;
while((in=getchar()) >'9' || in<'0');
}
num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
num*=10,num+=in-'0';
if(neg)
num=0-num;
}
void Update(int index, int tp) {
ans -= cube(s[c[index]]);
// ans -= (ll)s[c[index]]*s[c[index]]*s[c[index]];
s[c[index]] += tp;
ans += cube(s[c[index]]);
//ans += (ll)s[c[index]]*s[c[index]]*s[c[index]];
}
void solve() {
for(int i=1, l=1,r=0; i<=m; i++) {
if(q[i].l==q[i].r) {
q[i].ans=1;
continue;
}
for( ; r<q[i].r; r++) {
Update(r+1, 1);
}
for( ; r>q[i].r; r--) {
Update(r, -1);
}
for( ; l<q[i].l; l++) {
Update(l, -1);
}
for( ; l>q[i].l; l--) {
Update(l-1, 1);
}
q[i].ans = ans;
}
}
int main() {
while(scanf("%d", &n)!=EOF) {
memset(s, 0, sizeof(s)), ans = 0;
int block = (int)sqrt(n*1.0);
for(int i=1; i<=n; i++) scanf_(c[i]), pos[i] = (i-1)/block + 1,sub[i] = c[i];
scanf_(m);
for(int i=1; i<=m; i++) {
// scanf("%d%d", &q[i].l, &q[i].r);
scanf_(q[i].l);
scanf_(q[i].r);
q[i].id = i;
}
sort(sub+1, sub+n+1);
int Size = unique(sub+1, sub+n+1) - (sub+1);
for(int i=1; i<=n; i++) {
c[i] = lower_bound(sub+1, sub+Size+1, c[i]) - (sub+1);
}
sort(q+1, q+1+m, cmp);
solve();
sort(q+1, q+1+m, cmpId);
for(int i=1; i<=m; i++) {
printf("%I64d\n",q[i].ans);
}
}
return 0;
}
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define ll long long
using namespace std;
const int N = 200103;
int n, m, pos[N];
int c[N], sub[N], b[N];
ll s[N], ans;
bool vis[N];
struct node {
int l, r, id;
ll ans;
}q[N];
bool cmp(node a, node b) {
if(pos[a.l] == pos[b.l]) {
return a.r < b.r;
}
return a.l < b.l;
}
bool cmpId(node a, node b) {
return a.id < b.id;
}
inline void scanf_(int &num) {
char in;
bool neg=false;
while(((in=getchar()) > '9' || in<'0') && in!='-') ;
if(in=='-') {
neg=true;
while((in=getchar()) >'9' || in<'0');
}
num=in-'0';
while(in=getchar(),in>='0'&&in<='9')
num*=10,num+=in-'0';
if(neg)
num=0-num;
}
void Update(int index, int tp) {
s[c[index]] += tp;
if(s[c[index]] == b[index]+tp) ans--;
if(s[c[index]]==b[index]) ans++;
}
void solve() {
for(int i=1, l=1,r=0; i<=m; i++) {
for( ; r<q[i].r; r++) {
Update(r+1, 1);
}
for( ; r>q[i].r; r--) {
Update(r, -1);
}
for( ; l<q[i].l; l++) {
Update(l, -1);
}
for( ; l>q[i].l; l--) {
Update(l-1, 1);
}
q[i].ans = ans;
}
}
int main() {
while(scanf("%d%d", &n, &m)!=EOF) {
memset(s, 0, sizeof(s)), ans = 0;
int block = (int)sqrt(n*1.0), sum = 0;
for(int i=1; i<=n; i++){
scanf("%d", &c[i]);
sub[i] = c[i];
b[i] = c[i];
pos[i] = (i-1)/block + 1;
}
for(int i=1; i<=m; i++) {
scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
}
sort(sub+1, sub+n+1);
int Size = unique(sub+1, sub+n+1) - (sub);
for(int i=1; i<=n; i++) {
c[i] = lower_bound(sub+1, sub+Size, c[i]) - (sub);
}
sort(q+1, q+1+m, cmp);
solve();
sort(q+1, q+1+m, cmpId);
for(int i=1; i<=m; i++) {
printf("%lld\n",q[i].ans);
}
}
return 0;
}