日程管理
2016-03-27 14:45
176 查看
日程管理
时间限制: 2 Sec 内存限制: 512 MB题目描述
幽吞是幻想乡中一个非常有地位的人。她日理万机,事务繁多,感到自己已经快理不过来了。于是她决定开发一个日程管理软件来帮组自己管理任务。
对于每个任务i有一个对应的截止日期ti以及收益pi,表示若幽香能在不晚于第ti天完成这个任务,使可以得到pi的收益。幽香办事的能力非常强,任何任务部可以用恰好一天时间做完。但由于任务实在太多了,有时候并不能完成所有任务,于是幽香会想要知道这个情况下,完成任务可以给她带来最大的累积收益是多少。
由于幻想乡的人们十分善变,任务总是不断发生肴变化。幽香希望这个管理软件还能够支持插入一个任务,和删除一个任务的操作。
具体的说.幽香希t}支持以下7个操作:
1. ADD t p:表示新添一个截止日期为t,收益为p的任务。
2. DEL t p:表示删除一个截止日期为t,收益为p的任务。如果有多个这
样的任务,只删除一个。数据保证这样的任务一定存在。
在每次操作执行完毕后,你都甲需要输出能够完成的任务的最大收益和。
幽香一共有T天需要安排,从第1天到第T天,你能帮助她写出这个高效率的软件吗?
输入
第一行有两个正整数T和Q,表示天数和操作的个数。
接下来Q行,其中第i行表示第i个操作,形式为ADD t p或DEL t p,其具体意义如体面所述。
输出
要求对于每一次操作,输出一个整数在执行完该后幽香能获得的最大收益和。
样例输入
5 10
ADD 1 5811
ADD 3 5032
DEL 3 5032
ADD 3 5550
ADD 5 3486
DEL 1 5811
DEL 3 5550
ADD 4 5116
ADD 3 9563
ADD 5 94
样例输出
5811
10843
5811
11361
14847
9036
3486
8602
18165
18259
数据范围
T<=300000,Q<=300000
来源
ctsc2015 day2
题解
幽香。。陈老师的题。。假设只有一组询问,考虑贪心,将任务按照p排序,从大到小插入即可。
所以我们可以拿2棵线段树分别维护已经插入的和暂时未插入的任务。
为了方便操作,再写一棵线段树表示每个时间点能否再增加任务。
对于每次ADD操作,先在插入的t后面寻找一个最左边的不能增加任务的位置。如果找不到则显然直接加入这个任务。若找到了,则在【1,这个位置】这段区间内寻找最小值,并和这次操作的t比较即可。
对于每次DEL操作,如果没有插入,则直接删除即可。
考虑已经插入的情况,则显然应该寻找最后一个不能增加任务的位置,并选择t在这个位置之后的节点中p最小的来替代。
以上题解来自本蒟蒻口胡。
要看正常的题解的话去找cls的ppt。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<set> #include<algorithm> #define inf 1050000000 #define N 300005 using namespace std; int n,Q,ans; struct node{int minn,pos;}; struct info{int minn,tag;}; class seg_tree_2 { node merge(node a,node b) { if(a.minn<b.minn)return a; return b; } public: node t[N*4];multiset<int>q ; void build(int x,int l,int r) { if(l==r) { t[x].minn=inf;t[x].pos=l; q[l].insert(inf);return; } int mid=l+r>>1,lc=x<<1,rc=lc+1; build(lc,l,mid);build(rc,mid+1,r); t[x]=merge(t[lc],t[rc]); } void insert(int x,int l,int r,int ti,int p) { if(l==r) { t[x].minn=min(t[x].minn,p); q[l].insert(p);return; } int mid=l+r>>1,lc=x<<1,rc=lc+1; if(ti<=mid)insert(lc,l,mid,ti,p); else insert(rc,mid+1,r,ti,p); t[x]=merge(t[lc],t[rc]); } bool erase(int x,int l,int r,int ti,int p) { if(t[x].minn>p)return false; if(l==r) { q[l].erase(q[l].find(p)); t[x].minn=*q[l].begin(); return true; } int mid=l+r>>1,lc=x<<1,rc=lc+1,res; if(ti<=mid)res=erase(lc,l,mid,ti,p); else res=erase(rc,mid+1,r,ti,p); t[x]=merge(t[lc],t[rc]); return res; } node qry(int x,int l,int r,int ql,int qr) { if(ql<=l&&r<=qr)return t[x]; int mid=l+r>>1,lc=x<<1,rc=lc+1,res=0; if(qr<=mid)return qry(lc,l,mid,ql,qr); if(ql>mid)return qry(rc,mid+1,r,ql,qr); return merge(qry(lc,l,mid,ql,qr),qry(rc,mid+1,r,ql,qr)); } }T1,T2; class seg_tree { void pushdown(int x) { if(!t[x].tag)return; int lc=x<<1,rc=lc+1; t[lc].minn+=t[x].tag;t[lc].tag+=t[x].tag; t[rc].minn+=t[x].tag;t[rc].tag+=t[x].tag; t[x].tag=0; } void update(int x) { int lc=x<<1,rc=lc+1; t[x].minn=min(t[lc].minn,t[rc].minn); } public: info t[N*4]; void build(int x,int l,int r) { t[x].minn=l;t[x].tag=0; if(l==r)return; int mid=l+r>>1,lc=x<<1,rc=lc+1; build(lc,l,mid);build(rc,mid+1,r); } void modify(int x,int l,int r,int ql,int qr,int val) { if(ql<=l&&r<=qr){t[x].minn+=val;t[x].tag+=val;return;} int mid=l+r>>1,lc=x<<1,rc=lc+1; pushdown(x); if(ql<=mid)modify(lc,l,mid,ql,qr,val); if(qr>mid)modify(rc,mid+1,r,ql,qr,val); update(x); } int find_l(int x,int l,int r,int pos) { if(t[x].minn)return 0; if(l==r)return l; int mid=l+r>>1,lc=x<<1,rc=lc+1,tmp; pushdown(x); if(pos<=mid){if(tmp=find_l(lc,l,mid,pos))return tmp;} return find_l(rc,mid+1,r,pos); } int find_r(int x,int l,int r) { if(t[x].minn)return 0; if(l==r)return l; pushdown(x); int mid=l+r>>1,lc=x<<1,rc=lc+1,tmp; if(tmp=find_r(rc,mid+1,r))return tmp; return find_r(lc,l,mid); } }T; int main() { int ti,p;char s[5]; scanf("%d%d",&n,&Q); T.build(1,1,n);T1.build(1,1,n);T2.build(1,1,n); while(Q--) { scanf(" %s%d%d",s,&ti,&p); if(s[0]=='A') { int pos=T.find_l(1,1,n,ti); if(!pos) { ans+=p; T1.insert(1,1,n,ti,p); T.modify(1,1,n,ti,n,-1); } else { node x=T1.qry(1,1,n,1,pos); if(p>x.minn) { ans+=p-x.minn; T1.erase(1,1,n,x.pos,x.minn); T.modify(1,1,n,x.pos,n,1); T2.insert(1,1,n,x.pos,-x.minn); T1.insert(1,1,n,ti,p); T.modify(1,1,n,ti,n,-1); } else T2.insert(1,1,n,ti,-p); } } else { if(!T2.erase(1,1,n,ti,-p)) { ans-=p; T1.erase(1,1,n,ti,p); T.modify(1,1,n,ti,n,1); int pos=T.find_r(1,1,n); node x=T2.qry(1,1,n,pos+1,n); if(x.minn<=0) { ans-=x.minn; T2.erase(1,1,n,x.pos,x.minn); T1.insert(1,1,n,x.pos,-x.minn); T.modify(1,1,n,x.pos,n,-1); } } } printf("%d\n",ans); } return 0; }
相关文章推荐
- Unity3D热更新<二> 编辑器扩展和打包AssetBundle
- Oracle:高效插入大量数据经验之谈
- Droidbox恶意软件动态分析环境搭建
- Python2.7写入中文数据进sqlite3报错
- 张龙(风中叶)的忠告
- 排序后续
- HDP 2.4安装
- linux内核分析——扒开系统调用的三层皮(下)
- Java多线程系列--“JUC集合”06之 ConcurrentSkipListSet
- java网上商城开发之邮件发送功能(全)
- HTML DOM 访问
- 第4次作业(2)
- Android 使用无线调试
- 39. Combination Sum
- [go] database/sql包执行生成的SQL语句,遇到Incorrect Integer错误
- TransE算法(Translating Embedding)
- UITableViewcell autolayout下动态高度
- 位图
- for循环中有多个限制结束条件的正确写法(小心逗号运算符)
- vector的用法