题意:给一个序列,m次操作,每次操作给两个数,p,x,把a[p]改成x,问每次操作后中位数是多少
思路:修改用树状数组,将a[p]--,然后将x++;查询二分查询树状数组,查询值为1到mid的数字有多少个,如果是一半,则mid为中位数
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m;
int tree[N],a[N];
int lowbit(int x){
return x&-x;
}
void add(int x,int k){
for (int i = x; i <=N ; i+= lowbit(i)) {
tree[i]+=k;
}
}
int check(int x){
int res=0;
for (int i = x; i >0 ; i-= lowbit(i)) {
res+=tree[i];
}
return res;
}
int main(){
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>m;
for (int i = 1; i <=n ; ++i) {
cin>>a[i];
add(a[i],1);
}
int t=(n+1)/2;
while (m--){
int x,y;
cin>>x>>y;
add(a[x],-1),add(y,1);
a[x]=y;
int l=0,r=N;
int ans=-1;
while(l<=r){
int mid=l+r>>1;
if(check(mid)>=t)r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans<<endl;
}
}
题意:给一个图,松鼠由起点st到终点ed,每个点都会扣除松果,每条边都有一个长度,问从起点到终点的路径的长度和小于H的情况下,在路上扣除的最大的松鼠的数量最小是多少。
思路:二分,松鼠数量,djstl跑一遍最短路,最短距离是否小于H
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define int long long
int n,m,st,ed,h;
vector<PII>q[10004];
int d[10004];
signed main(){
cin>>n>>m>>st>>ed>>h;
for(int i=1;i<=n;i++)cin>>d[i];
while(m--){
int x,y,z;
cin>>x>>y>>z;
q[x].push_back({y,z});
q[y].push_back({x,z});
}
auto check=[&](int mid){
vector<int>vis(n+1,0),dis(n+1);
for(int i=0;i<=n;i++)dis[i]=1e9;
queue<int>g;
g.push(st);
dis[st]=0;
vis[st]=1;
while(g.size()){
auto t=g.front();
g.pop();
vis[t]=0;
for(auto u:q[t]){
int dian=u.first;
int b=u.second;
if(d[dian]>mid)continue;
if(dis[dian]>dis[t]+b){
dis[dian]=dis[t]+b;
if(vis[dian]==0){
vis[dian]=1;
g.push(dian);
}
}
}
}
if(h>=dis[ed])return true;
else return false;
};
int l=0,r=1e7;
int ans=-1;
while(l<=r){
int mid=l+r>>1;
if(check(mid))r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans<<endl;
}