CodePlus2017 12月月赛 div2火锅盛宴
当时看到这道题感觉真是难过,我数据结构太弱啦。
我们来看看需要求什么:
1、当前熟了的食物的最小id
2、当前熟了的食物中有没有编号为id的食物
3、当前没熟的食物中有没有编号为id的食物
4、当前没熟的食物中编号为id的食物最接近煮熟的还需要多久才会熟
5、当前熟了的食物中编号在[l,r]之间的有多少个
我们需要维护的操作是:
1、往当前的锅里面加一个编号为id的生食物
2、每个时刻锅里面哪些生的食物要变熟
3、吃掉(删除)一个熟了的食物
感觉这种题真考人做题的毅力,求的东西好杂感觉脑子里都乱套了。
我用了4个multiset+1个树状数组来水这道题。
4个multiset:
Hn : 存int,当前没熟的的食物的id(按照id顺序)
Hn2 : 存结构体,当前没熟的食物的id和熟的时间(按照熟的时间顺序)
now[maxn] : 存int,now[i]是id为i的未熟食物的熟的时间(按照熟的时间顺序)
Hd : 存int,当前熟了的食物的id(按照id顺序)
剩下还有一个树状数组用来求id在一个区间的熟了的食物的个数的。
感觉非常不优秀,但是当时剩下时间不多,就没有怎么优化。
注意multiset如果直接erase(x)会把所有值为x的都删掉,只删一个需要先find,再删。(感谢Achen)
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<set> using namespace std; const int maxn=1e5+10,maxm=5e5+10; int n,m,T,s[maxn]; struct Node{ int id,time; Node() {} Node(int id,int time):id(id),time(time){} bool operator < (const Node& b) const{ return time < b.time; } }; multiset<int> Hn; multiset<Node> Hn2; multiset<Node>::iterator it; multiset<int>::iterator it2; multiset<int> Hd; multiset<int> now[maxn]; int aa;char cc; int read() { aa=0;cc=getchar(); while(cc<'0'||cc>'9') cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); return aa; } int sz[maxn]; void chge(int pos,int x) { while(pos<=n) { sz[pos]+=x; pos+=pos&-pos; } } int q(int pos) { int rs=0; while(pos) { rs+=sz[pos]; pos-=pos&-pos; } return rs; } int main() { T=read(); int t,op,l,r,x; while(T--) { Hn.clear(); Hn2.clear(); Hd.clear(); for(int i=1;i<=n;++i) now[i].clear(); memset(sz,0,sizeof(sz)); n=read(); for(int i=1;i<=n;++i) s[i]=read(); m=read(); while(m--) { t=read(); op=read(); while(!Hn2.empty()) { it=Hn2.begin(); if(it->time>t) break; x=it->id; it2=Hn.find(x); Hn.erase(it2); Hd.insert(x); Hn2.erase(it); chge(x,1); while(!now[x].empty()) { it2=now[x].begin(); if(*it2>t) break; now[x].erase(it2); } } if(op==0) { x=read(); Hn2.insert(Node(x,t+s[x])); Hn.insert(x); now[x].insert(t+s[x]); } else if(op==1) { if(Hd.empty()) { printf("Yazid is angry.\n"); continue; } it2=Hd.begin(); printf("%d\n",*it2); chge(*it2,-1); Hd.erase(it2); } else if(op==2) { x=read(); if((it2=Hd.find(x))!=Hd.end()) { printf("Succeeded!\n"); chge(*it2,-1); Hd.erase(it2); } else if(Hn.find(x)!=Hn.end()) { it2=now[x].begin(); printf("%d\n",*it2-t); } else printf("YJQQQAQ is angry.\n"); } else if(op==3) { l=read(); r=read(); printf("%d\n",q(r)-q(l-1)); } } } return 0; }
弱者就是会被欺负呀