//一个for做两次前缀和,也就是在把前面已经有过的数字加一遍就可以了,用一个sum维护
//最大值只会出现在端点处,但是这里的端点,不等价于记录的点,而是前一个点
//然后找出每一个大于m的地方,这两个值的关系
//最后比较一次也就可以了
//收获:这样子进行差分,用vector进行维护的二阶差分,而不把所有的数都求出来
//极值只会在端点处
//对每个人造出的影响进行分析
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int M=1e6+5;
const int inf=1e15;
struct node {
int pos,k;
bool operator<(const node T)const {
if(pos!=T.pos)return pos<T.pos;
return k<T.k;
}
};
int n,m;
int x[M],p[M],d[M],mx,mn;
void up(int id,int v) {
if(v<=m)return ;
mx=max(mx,id+v-m);
mn=min(mn,id-v+m);
}
//从全局考虑影响
signed main() {
int TT;cin>>TT;
while(TT--) {
vector<node>v;
cin>>n>>m;
mx=-inf,mn=inf;
v.push_back({-inf,0});
v.push_back({inf,0});
for(int i=1;i<=n;i++) {
cin>>x[i]>>p[i];
v.push_back({x[i]-p[i]+1,1});
v.push_back({x[i]+1,-2});
v.push_back({x[i]+p[i]+1,1});
}
sort(v.begin(),v.end());
int pre=0;
for(int i=1;i<v.size()-1;i++) {
d[i]=d[i-1]+v[i].k;
if(v[i].pos!=v[i+1].pos) {
up(v[i].pos,pre+d[i]);
up(v[i+1].pos-1,pre+d[i]*(v[i+1].pos-v[i].pos));
}
pre+=d[i]*(v[i+1].pos-v[i].pos);
}
for(int i=1;i<=n;i++) {
if((x[i]+p[i])>=mx&&(x[i]-p[i])<=mn)cout<<"1";
else cout<<"0";
}
cout<<'\n';
}
return 0;
}
标签:--,CF,back,int,push,端点,810,inf
From: https://www.cnblogs.com/basicecho/p/16982992.html