使用VIM过的第二个题....
最多的错误是CE !!!
VIM的全选粘贴太麻烦了!!! ggVG"+y 纠结啊,经常粘错。。。呜呜
有一次粘错,把我代码所有大写都变成小写了,呜呜。。
这个题依旧线段树。开始没思路。。。看别人的了,唉。
离线做会好做写,按结束坐标排序,然后扫一遍,遇到重复的,就把之前插入线段树的给删掉。这样的话,删掉前面的不会影响后面的结果。
用树状数组快了很多。
线段树的:
#include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <string> #include <string.h> #include <algorithm> #define MID(x,y) ( ( x + y ) >> 1 ) #define L(x) ( x << 1 ) #define R(x) ( x << 1 | 1 ) #define FOR(i,s,t) for(int i=(s); i<(t); i++) #define file_r(x) freopen(x, "r", stdin) #define file_w(x) freopen(x, "w", stdout) using namespace std; const int MAX = 50010; const int MMAX = 1000010; typedef __int64 ll; int pre[MMAX]; struct NODE{ int x, y, id; void get() { scanf("%d%d", &x, &y); } }; NODE a[MAX*4]; int num[MAX]; ll ans[MAX*4]; struct Tnode{ int l,r; ll sum; int len() { return r - l;} int mid() { return MID(l,r);} bool in(int ll,int rr) { return l >= ll && r <= rr; } void lr(int ll,int rr){ l = ll; r = rr;} }; Tnode node[MAX<<2]; void Updata_sum(int t) { node[t].sum = node[L(t)].sum + node[R(t)].sum; } void Build(int t,int l,int r) { node[t].lr(l,r); node[t].sum = 0; if( node[t].len() == 1 ) return ; int mid = MID(l,r); Build(L(t),l,mid); Build(R(t),mid,r); } void Updata(int t,int l,int r,int val) { if( node[t].in(l,r) ) { node[t].sum = val; return ; } if( node[t].len() == 1 ) return ; int mid = node[t].mid(); if( l < mid ) Updata(L(t),l,r,val); if( r > mid ) Updata(R(t),l,r,val); Updata_sum(t); } ll Query(int t,int l,int r) { if( node[t].in(l,r) ) return node[t].sum; if( node[t].len() == 1 ) return 0; int mid = node[t].mid(); ll ans = 0ll; if( l < mid ) ans += Query(L(t),l,r); if( r > mid ) ans += Query(R(t),l,r); return ans; } bool cmp_y(NODE a, NODE b) { if( a.y == b.y ) return a.x < b.x; return a.y < b.y; } void solve(int n, int m) { sort(a, a+m, cmp_y); memset(pre, -1, sizeof(pre)); int st = 1; Build(1, 0, n); FOR(i, 0, m) { while( st <= a[i].y ) { if( pre[num[st]] == -1 ) { pre[num[st]] = st; Updata(1, st-1, st, num[st]); } else { int pos = pre[num[st]]; Updata(1, pos-1, pos, 0); pre[num[st]] = st; Updata(1, st-1, st, num[st]); } st++; } ans[a[i].id] = Query(1, a[i].x-1, a[i].y); } FOR(i, 0, m) printf("%I64d\n", ans[i]); } int main() { int ncases, n, m; scanf("%d", &ncases); while( ncases-- ) { scanf("%d", &n); FOR(i, 1, n+1) scanf("%d", &num[i]); scanf("%d", &m); FOR(i, 0, m) { a[i].id = i; a[i].get(); } solve(n, m); } return 0; }
树状数组的:
#include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <string> #include <string.h> #include <algorithm> #define FOR(i,s,t) for(int i=(s); i<(t); i++) #define file_r(x) freopen(x, "r", stdin) #define file_w(x) freopen(x, "w", stdout) using namespace std; const int MAX = 50010; const int MMAX = 1000010; typedef long long ll; int pre[MMAX]; struct NODE{ int x, y, id; void get() { scanf("%d%d", &x, &y); } }; NODE a[MAX*4]; int num[MAX]; ll c[MAX], ans[MAX*4]; int lowbit(int x) { return x & (-x); } void Updata(int x,int num)// num 可能都为1,具体问题具体分析 { int i; for(i=x; i<MAX; i+=lowbit(i)) c[i] += num; // 若num 为1,c[i]++ } ll Getsum(int x)//sum的返回值的类型可能是long long ,根据题意判断 { ll sum = 0; for(int i=x; i>0; i-=lowbit(i)) sum += c[i]; return sum; } bool cmp_y(NODE a, NODE b) { if( a.y == b.y ) return a.x < b.x; return a.y < b.y; } void solve(int n, int m) { sort(a, a+m, cmp_y); memset(pre, -1, sizeof(pre)); memset(c, 0, sizeof(c)); int st = 1; FOR(i, 0, m) { while( st <= a[i].y ) { if( pre[num[st]] == -1 ) { pre[num[st]] = st; Updata(st, num[st]); } else { int pos = pre[num[st]]; Updata(pos, -num[st]); pre[num[st]] = st; Updata(st, num[st]); } st++; } ans[a[i].id] = Getsum(a[i].y); if( a[i].x != 1 ) ans[a[i].id] -= Getsum(a[i].x-1); } FOR(i, 0, m) printf("%I64d\n", ans[i]); } int main() { int ncases, n, m; scanf("%d", &ncases); while( ncases-- ) { scanf("%d", &n); FOR(i, 1, n+1) scanf("%d", &num[i]); scanf("%d", &m); FOR(i, 0, m) { a[i].id = i; a[i].get(); } solve(n, m); } return 0; }