Gym 100960G (set+树状数组)

Problem Youngling Tournament

题目大意

  给一个序列a[i],每次操作可以更改一个数,每次询问 将序列排序后有多少个数a[i]>=sum[i-1]。

  n<=10^5,q<=5*10^4,a[i]<=10^12

解题分析

  可以发现,在最优情况下,该序列长度最多为logn。

  将询问离线后,用multiset来维护a[i],用树状数组来维护sum[i]。树状数组所存下标为离散化后的a[i]。

  每次查询时跳跃式地在set中查找。

  时间复杂度 O((n+m)log(n+m)+mlognlogn)

参考程序

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <string>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <cassert>
 13 #include <iostream>
 14 #include <algorithm>
 15 #pragma comment(linker,"/STACK:102400000,102400000")
 16 using namespace std;
 17
 18 #define N 100008
 19 #define M 50008
 20 #define LL long long
 21 #define lson l,m,rt<<1
 22 #define rson m+1,r,rt<<1|1
 23 #define clr(x,v) memset(x,v,sizeof(x));
 24 #define bitcnt(x) __builtin_popcount(x)
 25 #define rep(x,y,z) for (int x=y;x<=z;x++)
 26 #define repd(x,y,z) for (int x=y;x>=z;x--)
 27 const int mo  = 1000000007;
 28 const int inf = 0x3f3f3f3f;
 29 const int INF = 2000000000;
 30 /**************************************************************************/
 31
 32 int n,m,tot,flag;
 33 LL a[N],c[N],x[N*2];
 34 int b[N];
 35 multiset<long long> S;
 36 struct Binary_Indexed_Tree{
 37     LL a[N*3];
 38     void clear(){
 39         clr(a,0);
 40     }
 41     void insert(int x,LL val){
 42         for (int i=x;i<=N<<1;i+=i & (-i))
 43             a[i]+=val;
 44     }
 45     LL sigma(int x){
 46         LL res=0;
 47         for (int i=x;i>0;i-=i & (-i))
 48             res+=a[i];
 49         return res;
 50     }
 51     LL query(int x,int y){
 52         return sigma(y)-sigma(x-1);
 53     }
 54 }T;
 55 int id(LL xy){
 56     return lower_bound(x+1,x+tot+1,xy)-x;
 57 }
 58 set <long long> :: iterator it,it1;
 59 void query(){
 60     int ans=1; LL tmp;
 61     it = S.begin();
 62     it1 = it ; it1++;
 63     if (*it==*it1) ans++;
 64     tmp=T.sigma(id(*it));
 65     while (1){
 66         it = S.lower_bound(tmp);
 67         if (it==S.begin()) it++;
 68         if (it==S.end()) break;
 69         it1 = it; it1--;
 70         tmp=T.sigma(id(*it1));
 71         if (*it>=tmp) ans++;
 72         tmp=T.sigma(id(*it));
 73     }
 74     printf("%d\n",ans);
 75
 76 }
 77
 78 int main(){
 79     scanf("%d",&n);
 80     rep(i,1,n){
 81         scanf("%lld",&a[i]);
 82         x[++tot]=a[i];
 83     }
 84     scanf("%d",&m);
 85     rep(i,1,m){
 86         scanf("%d%lld",&b[i],&c[i]);
 87         x[++tot]=c[i];
 88     }
 89     sort(x+1,x+tot+1);
 90     tot=unique(x+1,x+tot+1)-x;
 91     T.clear();
 92     rep(i,1,n){
 93         T.insert(id(a[i]),a[i]);
 94         S.insert(a[i]);
 95     }
 96     query();
 97     rep(i,1,m){
 98         S.erase(S.find(a[b[i]]));
 99         T.insert(id(a[b[i]]),-a[b[i]]);
100         S.insert(c[i]);
101         T.insert(id(c[i]),c[i]);
102         a[b[i]]=c[i];
103         query();
104     }
105
106 }

时间: 2024-12-05 23:31:38

Gym 100960G (set+树状数组)的相关文章

Gym - 101755G Underpalindromity (树状数组)

Let us call underpalindromity of array b of length k the minimal number of times one need to increment some elements bj by 1 so that the array b would become a palindrome, that is, b1 = bk, b2 = bk - 1, and so on. The array of length n, consisting of

【树状数组】Gym - 101147J - Whistle&#39;s New Car

题意就是对每个点i,统计在其子树内(不含自身),且depj-depi<=xj的点有多少个. 把点分别按照dep-x和dep进行排序,离线处理, 每次把dep-x小于等于当前dep值的点插入树状数组,就变成了询问dfs序在一个区间内的点有多少个,可以用树状数组轻松解决. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int f,C; void R(int &am

Codeforces Gym 100114 H. Milestones 离线树状数组

H. Milestones Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Description The longest road of the Fairy Kingdom has n milestones. A long-established tradition defines a specific color for milestones in each region, with a

cf gym 100960 G. Youngling Tournament set+树状数组

G. Youngling Tournament time limit per test 2 seconds memory limit per test 256 mebibytes input standard input output standard output Yoda, the Grand Master of the Jedi Order, hit on the idea to hold a tournament among younglings. He has not chosen t

Gym - 100269F Flight Boarding Optimization(dp+树状数组)

原题链接 题意: 现在有n个人,s个位置和你可以划分长k个区域你可以把s个位置划分成k个区域,这样每个人坐下你的代价是该区域内,在你之前比你小的人的数量问你怎么划分这s个位置(当然,每个区域必须是连续的),才能使得总代价最小,输出代价. 分析:dp[i][j]表示第i个位置是第j个区域的结尾,dp[i][j]→dp[t][j+1]暴力转移.但是需要预处理每个范围里的代价值,需要树状数组维护. #include<bits/stdc++.h> using namespace std; const

【Codeforces】Gym 101156E Longest Increasing Subsequences LIS+树状数组

题意 给定$n$个数,求最长上升子序列的方案数 根据数据范围要求是$O(n\log n)$ 朴素的dp方程式$f_i=max(f_j+1),a_i>a_j$,所以记方案数为$v_i$,则$v_i=v_i+v_j,(f_i=f_j+1)$,利用lis的$O(n\log n)$树状数组做法同时维护长度和方案数 从通酱博客里还看到更详尽的解释:stackoverflow 时间复杂度$O(n\log n)$ 代码 #include <bits/stdc++.h> using namespace

Gym - 102082G What Goes Up Must Come Down (树状数组+贪心)

题意:有一个长度为n的序列,你每次可以选择两个相邻的元素交换,求把这个序列排成单峰序列的最少交换次数. 方法一:将元素按数值从大到小排序(保存原来的位置),把最大的插在中间,剩下的依次往两边放,依次考虑每个数该放在左边还是右边,只考虑后加入的数对已有的数的贡献.由于前面加入的数的次序对后加入的数无影响,因此贪心地选择贡献小的一边就行了.贡献为重排后下标的逆序数,注意大小相同的要特殊处理一下就行了. 1 #include<bits/stdc++.h> 2 using namespace std;

HDU - 6393 Traffic Network in Numazu (LCA+RMQ+树状数组)

这道题相当于将这两题结合: http://poj.org/problem?id=2763 http://codeforces.com/gym/101808/problem/K 题意:有N各点N条边的带权无向图(相当于一棵树多了一条边),两种操作:修改一条边的权值:求两点间的最短路径. 分析:将任意一条边取出来,其余n-1条边可以结合LCA解最短路.询问时,比较通过取出的边和仅通过树上的边的路径的大小,最小值就是两点的最短路径. 树状数组差分维护点到根节点的距离,根据dfs序来记录需要维护的范围.

[qbzt寒假]线段树和树状数组

树状数组 \(lowbit(x)=x\&(-x)\) 二维树状数组 修改某个点,查询(1,1)到(n,m)的前缀和(树状数组要从1开始) HDU2642 Stars \(YFF\)是个浪漫的人,他喜欢数天上的星星. 为了解决这个问题,我们考虑到天空是一个二维平面,有时星星会很亮,有时星星会很暗.首先,天空中没有明亮的星星,然后一些信息会被给出为"\(B\) \(x\) \(y\)",其中"\(B\)"表示明亮,\(x\)表示\(x\)坐标,\(y\)表示在\