loj#534. 「LibreOJ Round #6」花团

不难发现他在线是假的。

时间段立刻可以想到线段树分治,做法显然了。注意下时间点和时间段的转换。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <map>

#define ll long long

using namespace std;
int rd() {
	int f=1,sum=0; char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return sum*f;
}
ll lrd() {
	ll f=1,sum=0; char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return sum*f;
}
void pr(int x) {
	if(x<0) {putchar('-');x=-x;}
	if(x>9) pr(x/10);
	putchar(x%10+'0');
}
void lpr(ll x) {
	if(x<0) {putchar('-');x=-x;}
	if(x>9) lpr(x/10);
	putchar(x%10+'0');
}
/*
线段树分治是时间段! 0~1 一个时间段
*/
#define ls (cur<<1)
#define rs (ls|1)
#define max(A,B) (A>B?A:B)
#define il inline 

const int N=(int)(1.5e4+5);
struct node {
	int v,w;
};
basic_string<node>T[N<<2];
ll f[40][N],nm,ans;
int sum[N<<2],n,m,TT;

void update(int cur,int l,int r,int cl,int cr,int v,int w) {
	if(cl<=l&&r<=cr) {
		T[cur]+=((node){v,w}); ++sum[cur]; return ;
	}
	int mid=(l+r)>>1;
	if(cl<=mid) update(ls,l,mid,cl,cr,v,w);
	if(cr>mid) update(rs,mid+1,r,cl,cr,v,w);
	sum[cur]=sum[ls]+sum[rs];
}

void solve(int cur,int l,int r,int dep) {
	for(int i=0;i<T[cur].size();i++) {
		for(int j=m;j>=T[cur][i].v;j--) f[dep][j]=max(f[dep][j],f[dep][j-T[cur][i].v]+T[cur][i].w);
	}
	if(l==r) {
		int op=rd(),x,y,z;
		if(op==1) {
			x=rd(); y=rd(); z=rd();
			x-=TT*ans; y-=TT*ans; z-=TT*ans;
			update(1,1,n,l+1,z,x,y);
		} else {
			x=rd(); x-=TT*ans;
			if(f[dep][x]<0) {
				puts("0 0"); ans=0;
			} else {
				printf("1 %lld\n",f[dep][x]); ans=(f[dep][x]^1);
			}
		}
		return ;
	}
	int mid=(l+r)>>1;
	for(int i=0;i<=m;i++) f[dep+1][i]=f[dep][i];
	solve(ls,l,mid,dep+1);
	for(int i=1;i<=m;i++) f[dep+1][i]=f[dep][i];
	solve(rs,mid+1,r,dep+1);
}


int main() {
	//freopen("bag.5.1.in","r",stdin); freopen("bag.5.1.out","w",stdout);
	n=rd(); m=rd(); TT=rd();
	for(int i=1;i<=m;i++) f[0][i]=-1ll*(2e18);
	solve(1,1,n,0);
	return 0;
} 

  

posted @ 2021-08-21 22:56  FxorG  阅读(32)  评论(0编辑  收藏  举报