不难发现他在线是假的。
时间段立刻可以想到线段树分治,做法显然了。注意下时间点和时间段的转换。
#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 ",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; }