1 条题解
-
0
评分虚高。
首先获得的小费只和考煎饼的顺序有关。我们令烤煎饼的顺序为排列 ,那么不难直接写出答案。
$$Ans=\sum\limits_{i=1}^n L_{p_i}-\sum\limits_{j=1}^{i}T_{p_j}$$直接拆开算。
$$Ans=\sum\limits_{i=1}^n L_i-\sum\limits_{i=1}^{n}(n-i+1)T_{p_i}$$前者可以 维护。
对于后者,如果单次查询,我们直接对 从小到达排序。
我们还需要支持单点修改,也就是要在线维护每个数比它小的有多少个数,和比它小的数之和。
值域很小,直接开两个树状数组维护即可。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define pre(i,a,b) for(int i=a;i>=b;i--) #define N 200005 #define int long long using namespace std; int n,m,u[N],t[N],o[N],c[N][2],sum; inline void add(int x,int y,int op){for(;x<=N-5;x+=x&-x)c[x][op]+=y;} inline int ask(int x,int op){int sum=0;for(;x;x-=x&-x)sum+=c[x][op];return sum;} signed main(){ scanf("%lld%lld",&n,&m); rep(i,1,n)scanf("%lld%lld",&u[i],&t[i]),o[i]=t[i],sum+=u[i],add(t[i],1,0),add(t[i],t[i],1); sort(o+1,o+n+1);rep(i,1,n)sum-=o[i]*(n-i+1); printf("%lld\n",sum); while(m--){ int x;scanf("%lld",&x); sum -= u[x];add(t[x],-1,0);add(t[x],-t[x],1); int cur = ask(t[x],0),now = ask(t[x],1); sum += t[x] * (n - cur) + now; scanf("%lld%lld",&u[x],&t[x]); sum += u[x]; cur = ask(t[x],0),now=ask(t[x],1); sum -= t[x] * (n - cur) + now; add(t[x],1,0);add(t[x],t[x],1); printf("%lld\n",sum); } return 0; }
- 1
信息
- ID
- 4844
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 3
- 上传者