constint maxn = 100005; constint P = 99999997; int n;
structnode { int id, val; } a[maxn], b[maxn];
int T[maxn], m[maxn];
intlb(int i){ return i & (-i); }
boolcmp(node x, node y){ return x.val < y.val; }
voidadd(int i, int delta){ while (i <= n) { T[i] += delta; i += lb(i); } }
intsum(int i){ int rtn = 0; while (i > 0) { rtn += T[i]; i -= lb(i); } return rtn; }
intmain(){ cin >> n; for (int i = 1; i <= n; i ++) cin >> a[i].val; for (int i = 1; i <= n; i ++) { cin >> b[i].val; a[i].id = b[i].id = i; } sort(a + 1, a + 1 + n, cmp); sort(b + 1, b + 1 + n, cmp); for (int i = 1; i <= n; i ++) { m[a[i].id] = b[i].id; } int ans = 0; for (int i = 1; i <= n; i ++) { add(m[i], 1); ans = (ans + i - sum(m[i])) % P; } cout << ans << endl; return0; }
usingnamespacestd; constint maxn = 100005; constint P = 1000000009; int n, a[maxn],s[maxn];
int T[maxn];
intlb(int i){ return i & (-i); }
voidadd_sum(int i, int d){ // 由于数组的大小加了1,所以要n + 1 while (i <= n + 1) { T[i] = (T[i] + d) % P; i += lb(i); } }
intquery_sum(int i){ int ans = 0; while (i > 0) { ans = (ans + T[i]) % P; i -= lb(i); } return ans; }
intmain(){ cin >> n; for (int i = 1; i <= n; i ++) { cin >> a[i]; s[i] = s[i-1] + a[i]; a[i] = s[i]; } // 对s进行离散化 sort(a, a + n + 1); for(int i = 0; i <= n; i ++) s[i]=lower_bound(a, a + n + 1, s[i]) - a + 1; // 设置f[0] = 1, 此处的s[0]表示在原数组中第0号元素在离散化过的数组中的位置 add_sum(s[0], 1); int ans = 0; for (int i = 1; i <= n; i ++) { ans = query_sum(s[i]); add_sum(s[i], ans); } cout << ans << endl; return0; }
int n, p[maxn], head[maxn], cow[maxn], T[maxn], ans[maxn];
intlb(int i){ return i & (-i); }
voidmodify(int i, int delta){ while (i <= n) { T[i] += delta; i += lb(i); } }
intquery(int i){ int ret = 0; while (i > 0) { ret += T[i]; i -= lb(i); } return ret; }
structedge { int to, next; } g[maxn * 2];
int ecnt = 2;
voidadd_edge(int u, int v){ g[ecnt] = (edge) {v, head[u]}; head[u] = ecnt ++; }
voiddfs(int u, int fa){ int current = cow[u]; // 这个头牛的答案就是查询:树状数组当中编号比它小的,在路径上的个数和 ans[current] = query(current); // 刚刚进入这个节点(及其子树),所以把这个节点加入树状数组 modify(current, 1); for (int e = head[u]; e != 0; e = g[e].next) if (g[e].to != fa) dfs(g[e].to, u); // 即将退出该节点,再也不会访问到,所以将其从树状数组中删除 modify(current, -1); }
intmain(){ cin >> n; for (int i = 1; i < n; i ++) { int a, b; cin >> a >> b; add_edge(a, b); add_edge(b, a); } for (int i = 1; i <= n; i ++) { cin >> p[i]; cow[p[i]] = i; } dfs(1, 0); for (int i = 1; i <= n; i ++) { cout << ans[i] << endl; } return0; }
intquery(int x){ int pos = 0; // 第一次查询的区间最大,其后每次减半,相当于二分,但这里访问T数组的时间复杂度为O(1),故时间复杂度为O(log n)而不是O(log^2 n) for (int i = maxx; i > 0; i >>= 1) { // 更新位置 int j = i + pos; // 整个过程相当于在进行lb,所以x代表直到pos的前缀和与原来所求的差值,即距query目标还差的一部分 if (j <= n && T[j] <= x) { pos = j; x -= T[j]; } } return pos + 1; }
voidmodify(int i, int d){ while (i <= n) { T[i] += d; i += lb(i); } }
intmain(){ scanf("%d", &n); // O(n)时间建树状数组,原因是a[i]=1 for (int i = 1; i <= n; i ++) T[i] = lb(i); int r = 0; for (int m = n; m > 0; m --) { int s; scanf("%d", &s); r = (r + s) % m; // 在树状数组当中查询值为r的位置,时间复杂度为O(n) int pos = query(r); // 由于这张牌被发掉了,所以应该将这张牌从树状数组当中移除 modify(pos, -1); // 答案就为这个位置编号 printf("%d\n", pos); } return0; }