http://acm.fzu.edu.cn/problem.php?pid=2236
思路:每次找到当前第i个数之前有多少个比第i个数小的数,将前边的情况累加起来并且加上1
线段树查找,离散化
#include <iostream> #include <stdio.h> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <cstdlib> #include <algorithm> using namespace std; typedef long long LL; #define N 200000 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define MOD 1000000007 #define met(a, b) memset (a, b, sizeof(a)) const double EPS = 1e-8; struct node { int l, r, sum; }tree[N*4]; int val[N], Hash[N]; void Build (int rt, int l, int r) { tree[rt].l = l, tree[rt].r = r; tree[rt].sum = 0; if (l == r) return; int mid = (l+r)/2; Build (rt<<1, l, mid); Build (rt<<1|1, mid+1, r); } void Insert (int rt, int x, int sum) { tree[rt].sum = (tree[rt].sum+sum) % MOD; if (tree[rt].l == tree[rt].r) return; int mid = (tree[rt].l+tree[rt].r)/2; if (x<=mid) Insert (rt<<1, x, sum); else Insert (rt<<1|1, x, sum); } int Query (int rt, int l, int r) { if (l > r) return 0; if (tree[rt].l == l && tree[rt].r == r) return tree[rt].sum; int mid = (tree[rt].l+tree[rt].r)/2; if (r <= mid) return Query (rt<<1, l, r); else if (l > mid) return Query (rt<<1|1, l, r); else { int a = Query (rt<<1, l, mid); int b = Query (rt<<1|1, mid+1, r); return (a+b)%MOD; } } int main () { int n; while (scanf ("%d", &n) != EOF) { for (int i=0; i<n; i++) { scanf ("%d", &val[i]); Hash[i] = val[i]; } Hash[n] = 0; sort (Hash, Hash+n+1); int hs = unique (Hash, Hash+n+1) - Hash; Build (1, 1, hs+1); for (int i=0; i<n; i++) { int id = lower_bound (Hash, Hash+hs+1, val[i])-Hash; int sum = Query (1, 1, id-1); Insert (1, id, sum+1); } int ans = Query (1, 1, hs+1); printf ("%d\n", ans); } return 0; }