zoukankan      html  css  js  c++  java
  • GYM350340K.King Kog's Reception(巧妙的线段树)

    维护一个队列,每个人有抵达时间和操作时间。

    要求维护以下三种操作:

    1)t时刻来一个人,它操作需要d秒。

    2)t时刻要来的那个人不来了。

    3)如果t时刻去排队,需要等多久才能轮到你。

    做法:

    巧妙的线段树,以时间为下标建树,每个节点维护两个信息:

    1)这个区间内所有来的人的操作时间之和c。

    2)完成这个区间内所有人的最早截至时间mx。

    那么有转移方程:

    1)c[i]=c[i<<1]+c[i<<1|1]

    2)mx[i]=max(mx[i<<1]+c[i<<1|1],mx[i<<1|1])

    正常单点修改+区间查询。

    有点线段树上树形DP的感觉。很牛,我确实想不到,一种船新的技巧。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    int q;
    long long mx[maxn<<2],c[maxn<<2];
    void build (int i,int l,int r) {
    	if (l==r) {
    		mx[i]=l;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(i<<1,l,mid);
    	build(i<<1|1,mid+1,r);
    	c[i]=c[i<<1]+c[i<<1|1];
    	mx[i]=max(mx[i<<1]+c[i<<1|1],mx[i<<1|1]);
    } 
    void up (int i,int l,int r,int p,int v) {
    	if (l==r) {
    		c[i]+=v;
    		mx[i]+=v;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if (p<=mid) up(i<<1,l,mid,p,v);
    	if (p>mid) up(i<<1|1,mid+1,r,p,v);
    	c[i]=c[i<<1]+c[i<<1|1];
    	mx[i]=max(mx[i<<1]+c[i<<1|1],mx[i<<1|1]);
    }
    pair<long long,long long> query (int i,int l,int r,int L,int R) {
    	if (l>=L&&r<=R) return {c[i],mx[i]};
    	pair<long long,long long> ans={0,0};
    	int mid=(l+r)>>1;
    	if (L<=mid) {
    		pair<long long,long long> tt=query(i<<1,l,mid,L,R);
    		ans.first=ans.first+tt.first;
    		ans.second=max(ans.second+tt.first,tt.second);
    	}
    	if (R>mid) {
    		pair<long long,long long> tt=query(i<<1|1,mid+1,r,L,R);
    		ans.first=ans.first+tt.first;
    		ans.second=max(ans.second+tt.first,tt.second);
    	}
    	return ans;
    }
    pair<int,int> qq[maxn];
    int main () {
    	cin>>q;
    	int mm=1e6;
    	build(1,1,mm);
    	for (int i=1;i<=q;i++) {
    		//getchar();
    		char op;
    		int t,d;
    		cin>>op;
    		if (op=='?') {
    			int x;
    			cin>>x;
    			printf("%lld
    ",query(1,1,mm,1,x).second-x);
    		}
    		else if (op=='+') {
    			int t,d;
    			cin>>t>>d;
    			qq[i]={t,d};
    			up(1,1,mm,t,d);
    		}
    		else {
    			int p;
    			cin>>p;
    			up(1,1,mm,qq[p].first,-qq[p].second);
    		}
    	}
    }
  • 相关阅读:
    jquery更改输入框type为密码框password
    用table做网页,设置了border为1px怎么还是觉得很粗?
    键盘按钮keyCode大全
    兼容firefox的 keyCode
    php生成随机字符串和验证码的类
    asp.net多图片上传实现程序代码
    asp.net图片上传实例
    纯js分页代码(简洁实用)
    jQuery中读取json文件示例代码
    perl编程中的map函数示例
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15440866.html
Copyright © 2011-2022 走看看