Uoj 285 数据分块鸡

Uoj 285 数据分块鸡

决策单调性+二维数点。

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
inline int read(){
    int x=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x;
}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=50000+233;
int n,q;
mp seg[100000+123];
int dp[MAXN];
const int N=1<<16;
struct node{
	LL val;
	int cnt;
	int lc,rc;
	node(){val=cnt=0;}
};
inline pair<LL,int> operator + (pair<LL,int> A,pair<LL,int > B){return II(A.FIR+B.FIR,A.SEC+B.SEC);}
struct SEGMENTTREE{
	node tree[N+N+17*100000+233];
	int root[N];
	int cnt;
	void upd(int now){
		tree[now].val=tree[tree[now].lc].val+tree[tree[now].rc].val;
		tree[now].cnt=tree[tree[now].lc].cnt+tree[tree[now].rc].cnt;
	}
	SEGMENTTREE(){
		root[0]=1;
		cnt=N+N-1;
		rb(i,1,N){
			tree[i+N-1].lc=tree[i+N-1].rc=0;
			tree[i+N-1].val=0;
		}
		rl(i,N-1,1){
			tree[i].lc=i<<1;
			tree[i].rc=i<<1|1;
			tree[i].val=0;
		}
	}
	pair<LL,int> query_cnt(int a,int b,int now,int l=1,int r=N+1){
		if(r<=a||l>=b){
			return II(0,0);
		}
		if(r<=b&&l>=a){
			return II(tree[now].val,tree[now].cnt);
		}
		int mid=(l+r)>>1;
		if(mid<=a) return query_cnt(a,b,tree[now].rc,mid,r);
		else if(mid>=b) return query_cnt(a,b,tree[now].lc,l,mid);
		return query_cnt(a,b,tree[now].lc,l,mid)+query_cnt(a,b,tree[now].rc,mid,r);
	}
	void modify(int pos,int val,int& now,int l=1,int r=N+1){
		if(l==r-1){
			tree[++cnt]=tree[now];
			tree[cnt].val+=val;
			tree[cnt].cnt++;
			now=cnt;
			return ;
		}
		int mid=(l+r)>>1;
		int Now=++cnt;
		tree[Now]=tree[now];
		if(mid>pos)
		modify(pos,val,tree[Now].lc,l,mid);
		if(mid<=pos)
		modify(pos,val,tree[Now].rc,mid,r);
		upd(Now);
		now=Now;
	}
}sgtll,sgtrl,sgtrg;
LL query(int l,int r){
	int mid=(l+r-1)>>1;
	LL ret=sgtll.query_cnt(r,n+1,sgtll.root[l]).SEC;
	pair<LL,int> z=sgtrl.query_cnt(l,r+1,sgtrl.root[r]);
	ret+=1ll*(r-l+1)*z.SEC;
	ret-=z.FIR;
	z=sgtll.query_cnt(l,min(r,mid+1),sgtll.root[l-1]);
	ret+=z.FIR;
	ret-=1ll*(l-1)*z.SEC;
	z=sgtll.query_cnt(mid+1,r,sgtll.root[l-1]);
	ret-=z.FIR;
	ret+=1ll*(r)*z.SEC;
	mid=(l+r+2)>>1;
	z=sgtrg.query_cnt(max(l+1,mid),r+1,sgtrg.root[r+1]);
	ret-=z.FIR;
	ret+=1ll*(r+1)*z.SEC;
	z=sgtrg.query_cnt(l+1,mid,sgtrg.root[r+1]);
	ret+=z.FIR;
	ret-=1ll*l*z.SEC;
	return ret;
}
bool cmp(mp A,mp B){
	return A.SEC<B.SEC;
}
pair<int,mp> v[MAXN*2];
int main(){
	scanf("%d%d",&n,&q);
	--n;
	rb(i,1,q){
		seg[i].first=read();
		seg[i].SEC=read();
		seg[i].SEC--;
	}
	sort(seg+1,seg+1+q);
	int now=1;
	rb(i,1,n){
		sgtll.root[i]=sgtll.root[i-1];
		while(now!=q+1&&seg[now].FIR==i){
			sgtll.modify(seg[now].SEC,seg[now].SEC,sgtll.root[i]);
			++now;
		}
	}
	sort(seg+1,seg+1+q,cmp);
	now=1;
	rb(i,1,n){
		sgtrl.root[i]=sgtrl.root[i-1];
		while(now!=q+1&&seg[now].SEC==i){
			sgtrl.modify(seg[now].FIR,seg[now].SEC-seg[now].FIR+1,sgtrl.root[i]);
			++now;
		}
	}
	reverse(seg+1,seg+1+q);
	now=1;
	sgtrg.root[n+1]=1;
	rl(i,n,1){
		sgtrg.root[i]=sgtrg.root[i+1];
		while(now!=q+1&&seg[now].SEC==i){
			sgtrg.modify(seg[now].FIR,seg[now].FIR,sgtrg.root[i]);
			++now;
		}
	}
	int head=0,tail=-1;
	v[++tail]=(II(0,II(1,n)));
	rb(i,1,n){
		pair<int,mp> now=v[head++];
		dp[i]=dp[now.first]+query(now.FIR+1,i);
		if(n==i) break;
		now.second.FIR++;
		if(now.SEC.FIR>now.SEC.SEC);
		else v[--head]=now;
		int to=n+1;
		while(head<=tail){
			int j=tail;
			if(dp[v[j].FIR]+query(v[j].FIR+1,v[j].SEC.FIR) >= dp[i]+query(i+1,v[j].SEC.FIR) ){
				to=v[j].SEC.FIR;
				tail--;
			}
			else break;
		}
		if(head<=tail){
			int j=tail;
			int l=v[j].SEC.FIR+1,r=v[j].SEC.SEC;
			if(dp[v[j].FIR]+query(v[j].FIR+1,r) >= dp[i] + query(i+1,r) ){
				while(l<r){
					int mid=(l+r)>>1;
					if(dp[v[j].FIR]+query(v[j].FIR+1,mid) >= dp[i] + query(i+1,mid)) r=mid;
					else l=mid+1; 
				}
				to=l;
				pair<int,mp> ba=v[j];
				ba.second.SEC=to-1;
				v[tail]=ba;
			}
		}
		if(to!=n+1)
			v[++tail]=(II(i,II(to,n)));
	}
	cout<<dp[n]<<endl;
	return 0;
}
posted @ 2021-02-28 09:58  WWW~~~  阅读(62)  评论(0编辑  收藏  举报