1. 程式人生 > 實用技巧 >[日常摸魚]統一省選2020(未完)

[日常摸魚]統一省選2020(未完)

統一省選2020

前言

這就是卡常大賽嗎,i了i了。

冰火戰士

連結

http://uoj.ac/problem/539

題解

感覺題目還是簡單的,但是想要現場A掉應該是不容易的(樹狀陣列的就當我沒說),我的第一想法是線段樹。。算是勉強能過。。
直接線段樹的話時間效率是\(O(nlogn)\) ,空間效率也是\(O(nlogn)\) ,然而這樣會\(MLE\) 。容易發現答案一定出現在某個戰士的位置,離散化之後空間效率就可壓到\(O(n)\) 。就可以通過了。。注意常數!注意常數!注意常數!(樹狀陣列的當我沒說)

\(Code\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define LL long long
using namespace std;
const int N=2e6+10;
const int M=2e9+10; 
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void print(int x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int n,top=0;

int opt[N],tt[N],xx[N],yy[N];
int ansl,ansr;
int p[N<<1];
struct node{
	int ls,rs,v[2];
}a[N];
int get(int x){
	int l=1,r=top,mid;
	while(l<=r){
		mid=l+r>>1;
		if(p[mid]==x) return mid;
		if(x>p[mid]) l=mid+1;
		else r=mid-1;
	}
}
int main(){
	int T,op,l,r,x,i,mid;T=read();
	int L,R;
	for(int j=1;j<=T;++j){
		opt[j]=read();
		if(opt[j]==1){
			tt[j]=read();xx[j]=read();yy[j]=read();
			p[++top]=xx[j];
		}
		else{
			tt[j]=read();
		}
	}
	sort(p+1,p+1+top);
	n=top;
	for(int i=1;i<=n;++i) if(p[i]!=p[i-1]) p[++top]=p[i];
	n=1;
	for(int j=1;j<=T;++j){
		op=opt[j];
		if(op==1){
			i=j;
			xx[i]=get(xx[i]);
			l=1;r=top;x=1;
			while(1){
				a[x].v[tt[i]]+=yy[i];
				mid=l+r>>1;
				if(mid==xx[i]) break;
				if(xx[i]>mid){
					if(!a[x].rs) a[x].rs=++n;
					l=mid+1;x=a[x].rs;
				}
				else {
					if(!a[x].ls) a[x].ls=++n;
					r=mid-1;x=a[x].ls;
				}
			}
		}
		else{
			i=tt[j];
			l=1;r=top;x=1;
			while(1){
				a[x].v[tt[i]]-=yy[i];
				mid=l+r>>1;
				if(mid==xx[i]) break;
				if(xx[i]>mid){l=mid+1;x=a[x].rs;}
				else {r=mid-1;x=a[x].ls;}
			}
		}
		l=1;r=top;x=1;L=0;R=0;ansl=0;ansr=0;
		while(l<=r){
			if(a[x].v[0]+a[x].v[1]){
				mid=l+r>>1;
				op=min(L+a[x].v[0]-a[a[x].rs].v[0],R+a[x].v[1]-a[a[x].ls].v[1]);
				if(op>ansr||(op==ansr&&mid>ansl)){ansl=mid;ansr=op;}
				if(L+a[x].v[0]-a[a[x].rs].v[0]<=R+a[x].v[1]-a[a[x].ls].v[1]){
					L=L+a[x].v[0]-a[a[x].rs].v[0];l=mid+1;x=a[x].rs;
				}
				else{
					R=R+a[x].v[1]-a[a[x].ls].v[1];r=mid-1;x=a[x].ls;
				}
			}
			else{
				mid=r;op=min(L,R);
				if(op>ansr||(op==ansr&&mid>ansl)){ansl=mid;ansr=op;}
				break;
			}
		}
		l=1;r=top;x=1;L=0;R=0;
		while(l<=r){
			if(a[x].v[0]+a[x].v[1]){
				mid=l+r>>1;
				op=min(L+a[x].v[0]-a[a[x].rs].v[0],R+a[x].v[1]-a[a[x].ls].v[1]);
				if(op==ansr){
					if(mid>ansl) ansl=mid;
					L=L+a[x].v[0]-a[a[x].rs].v[0];l=mid+1;x=a[x].rs;
					continue;
				}
				if(L+a[x].v[0]-a[a[x].rs].v[0]<=R+a[x].v[1]-a[a[x].ls].v[1]){
					L=L+a[x].v[0]-a[a[x].rs].v[0];l=mid+1;x=a[x].rs;
				}
				else{
					R=R+a[x].v[1]-a[a[x].ls].v[1];r=mid-1;x=a[x].ls;
				}
			}
			else{
				mid=r;op=min(L,R);
				if(op>ansr||(op==ansr&&mid>ansl)){ansl=mid;ansr=op;}
				break;
			}
		}
		if(!ansr) printf("Peace\n");
		else {
			print(p[ansl]);putchar(' ');print(ansr<<1);puts("");
		}
	}
	return 0;
}