模拟赛原题。
听到机房大佬 sbh 说 log2n 不如 n,蒟蒻突发奇想,能不能用分块做到修改 O(n) 询问 O(1) 卡过去呢?
然后在 O2 加持下卡了 90pts,提交记录
求卡过去捏
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
typedef long long ll;
const int N=2e6+5;
int n,m,op[N],X[N],Y[N],Z[N],l,r,mid;
int b[N],R,K,L,l2,pos[N];
struct BIT{
ll c[N],c2[N];
void add(int x,int y){
for(register int i=x;pos[i]==pos[x];i++) c[i]+=y;
for(register int i=pos[x];i<=L;i++) c2[i]+=y;
}
ll query(int x){return x<0?0:(pos[x]?c2[pos[x]-1]+c[x]:c[x]);}
}A,B;
inline ll val(int x){return min(A.query(x),B.query(R)-B.query(x-1));}
char *p1,*p2,buf[10000005];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,10000000,stdin),p1==p2)?EOF:*p1++)
int read(){
int x=0,f=1;char ch=nc();
while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}
while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();
return x*f;
}
int main(){
// freopen("icefire.in","r",stdin);
// freopen("icefire.out","w",stdout);
m=read();
for(register int i=1;i<=m;++i){
op[i]=read();
if(op[i]==1) X[i]=read(),Y[i]=read(),Z[i]=read(),b[++R]=Y[i];
else X[i]=read();
}
sort(b+1,b+R+1);
R=unique(b+1,b+R+1)-b-1;
K=max((int)(sqrt(R)),1);
for(register int i=0;i<=R;i++)
L=max(L,pos[i]=i/K+1);
for(register int i=1;i<=m;i++)
if(op[i]==1)
Y[i]=lower_bound(b+1,b+R+1,Y[i])-b;
for(register int i=1;i<=m;i++){
if(op[i]==1){
if(!X[i]) A.add(Y[i],Z[i]);
else B.add(Y[i],Z[i]);
}
else{
if(!X[X[i]]) A.add(Y[X[i]],-Z[X[i]]);
else B.add(Y[X[i]],-Z[X[i]]);
}
l=0,r=R;
while(l<r){
mid=l+r+1>>1;
if(A.query(mid)<B.query(R)-B.query(mid-1)) l=mid;
else r=mid-1;
}
if(!val(l)&&!val(l+1)) puts("Peace");
else{
while(val(l+1)>=val(l)) l++;
printf("%d %lld\n",b[l],val(l)<<1);
}
}
return 0;
}