日程管理

来源:互联网 发布:淘宝网英文版 编辑:程序博客网 时间:2024/04/27 17:54

日程管理

时间限制: 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 300005using 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[N];  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;} 
0 0
原创粉丝点击