题目链接:
http://www.51nod.com/contest/problem.html#!problemId=1394
题目描述:
Input
第一行输入两个整数n,Q表示集合中初始元素个数和操作次数。(1<=n,Q<=100,000) 第二行给出n个整数a[0],a[1],a[2],…,a[n-1],表示初始集合中的元素。(0<=a[i]<=1,000,000,000) 接下来Q行,每行一个操作。(0<=v<=1,000,000,000)
Output
对于第2类操作,如果集合中不存在值为v的元素可供删除,输出-1。 对于第3类操作,输出答案。
Input示例
3 5 1 2 3 3 1 4 3 2 2 3
Output示例
4 10 6
大致思路:把所有操作离线,把涉及到的数离散化,然后用树状数组维护比此数小的所有数的和,比此数小的所有数的个数,就能Ologn 询问出操作3了。
离散化用了Java的hashmap
代码:
import java.util.HashMap;
import java.util.Map;
import java.math.*;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
InputStream inputStream = System.in;
OutputStream outputStream = System.out;
Scanner in = new Scanner(inputStream);
PrintWriter out = new PrintWriter(outputStream);
TaskE solver = new TaskE();
solver.solve(1, in, out);
out.close();
}
static int tp = 0;
static class TaskE {
static int n, Q;
public void solve(int testNumber, Scanner in, PrintWriter out) {
n = in.nextInt();
Q = in.nextInt();
Map<Integer, Integer> mp = new HashMap<Integer, Integer>();
int num[] = new int[n + 10];
int cnt[] = new int[n + Q + 10];
int all[] = new int[n + Q + 10];
int vs[] = new int[n + Q + 10];
int top = 0;
for(int i = 0; i < n; i ++) {
num[i] = in.nextInt();
all[top ++] = num[i];
}
pii qry[] = new pii[Q];
for(int i = 0; i < Q; i ++) qry[i] = new pii(0, 0);
for(int i = 0; i < Q; i ++) {
qry[i].X = in.nextInt();
if(qry[i].X == 3) continue;
qry[i].Y = in.nextInt();
all[top ++] = qry[i].Y;
}
Arrays.sort(all, 0, top);;
for(int i = 0; i < top; i ++) {
int it = all[i];
if(mp.containsKey(it)) continue;
mp.put(it, ++tp);
vs[tp] = it;
}
BIT A = new BIT();
BIT B = new BIT();
long sumval = 0, cur = 0, sumc = 0;
for(int i = 0; i < n; i ++ ) {
int val = num[i];
int id = mp.get(val);
long sufval = A.query(id);
long sufcnt = B.query(id);
cur += sufcnt * val - sufval;
cur += (sumval - sufval) - (sumc - sufcnt) * val;
sumval += val;
sumc ++;
A.update(id, val);
B.update(id, 1);
cnt[id] ++;
}
for(int i = 0; i < Q; i ++) {
int op = qry[i].X;
if(op == 3) {
out.println(cur);
out.flush();
} else if(op == 1) {
int val = qry[i].Y;
int id = mp.get(val);
long sufval = A.query(id);
long sufcnt = B.query(id);
cur += sufcnt * val - sufval;
cur += (sumval - sufval) - (sumc - sufcnt) * val;
sumval += val;
sumc ++;
A.update(id, val);
B.update(id, 1);
cnt[id] ++;
} else if(op == 2) {
int val = qry[i].Y;
int id = mp.get(val);
if(cnt[id] == 0) {
out.println("-1");
out.flush();
continue;
}
long sufval = A.query(id);
long sufcnt = B.query(id);
cur -= sufcnt * val - sufval;
cur -= (sumval - sufval) - (sumc - sufcnt) * val;
sumval -= val;
sumc --;
A.update(id, -val);
B.update(id, -1);
cnt[id] --;
}
}
}
}
static class BIT {
long sum[] = new long[tp + 100];
int lowbit(int x) {
return x & -x;
}
public void update(int id,long val) {
for(int i = id; i <= tp ; i += lowbit(i)) sum[i] += val;
}
public long query(int id) {
long ans = 0;
for(int i = id; i != 0; i -= lowbit(i))
ans += sum[i];
return ans;
}
}
static class pii implements Comparable<pii> {
int X, Y;
pii(int X, int Y) {
this.X = X;
this.Y = Y;
}
public int compareTo(pii a) {
if(this.X - a.X != 0) return this.X - a.X;
else return this.Y - a.Y;
}
}
static class Scanner {
BufferedReader br;
StringTokenizer st;
public Scanner(InputStream in) {
br = new BufferedReader(new InputStreamReader(in));
eat("");
}
private void eat(String s) {
st = new StringTokenizer(s);
}
public String nextLine() {
try {
return br.readLine();
} catch (IOException e) {
return null;
}
}
public boolean hasNext() {
while (!st.hasMoreTokens()) {
String s = nextLine();
if (s == null)
return false;
eat(s);
}
return true;
}
public String next() {
hasNext();
return st.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
public int[] nextIntArray(int n) {
int[] is = new int[n];
for (int i = 0; i < n; i++) {
is[i] = nextInt();
}
return is;
}
public long[] nextLongArray(int n) {
long[] ls = new long[n];
for (int i = 0; i < n; i++) {
ls[i] = nextLong();
}
return ls;
}
public double[] nextDoubleArray(int n) {
double[] ds = new double[n];
for (int i = 0; i < n; i++) {
ds[i] = nextDouble();
}
return ds;
}
public BigInteger[] nextBigIntegerArray(int n) {
BigInteger[] bs = new BigInteger[n];
for (int i = 0; i < n; i++) {
bs[i] = nextBigInteger();
}
return bs;
}
public int[][] nextIntMatrix(int row, int col) {
int[][] mat = new int[row][];
for (int i = 0; i < row; i++) {
mat[i] = nextIntArray(col);
}
return mat;
}
public long[][] nextLongMatrix(int row, int col) {
long[][] mat = new long[row][];
for (int i = 0; i < row; i++) {
mat[i] = nextLongArray(col);
}
return mat;
}
public double[][] nextDoubleMatrix(int row, int col) {
double[][] mat = new double[row][];
for (int i = 0; i < row; i++) {
mat[i] = nextDoubleArray(col);
}
return mat;
}
public BigInteger[][] nextBigIntegerMatrix(int row, int col) {
BigInteger[][] mat = new BigInteger[row][];
for (int i = 0; i < row; i++) {
mat[i] = nextBigIntegerArray(col);
}
return mat;
}
}
}