do_while_true

一言(ヒトコト)

「题解」Codeforces 1765L Project Manager

写了两个小时写吐了,你告诉我这玩意 2400?

如果不管假期的话,那么每一周必然会有一个项目跟进一次进度。那么答案就是线性的。即使有假期的存在也没关系,每个假期顶多就只会拖延一周的时间。

所以只需要暴力模拟每一天有哪些人工作了,完成了哪些项目的一个进度就可以了。

我的方法是对每个星期几维护一个 set,表示在这一天可能会工作的人,然后对每个人再开一个堆,存储这个人任务计划中的项目。

一个人可能在好几个星期几中工作,但是对于一个项目他只会工作一次,所以要搞个类似懒惰删除的东西,在一个人的任务计划里面找项目的时候需要判一下这个项目目前需不需要这个人来做。

然后就代码写得比较长......好像有更简单的写法。

#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<map>
#include<string>
#include<random>
#include<assert.h>
#include<set>
#define pb emplace_back
#define mp make_pair
#define fi first
#define se second
#define dbg(x) cerr<<"In Line "<< __LINE__<<" the "<<#x<<" = "<<x<<'\n'
#define dpi(x,y) cerr<<"In Line "<<__LINE__<<" the "<<#x<<" = "<<x<<" ; "<<"the "<<#y<<" = "<<y<<'\n'
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef pair<ll,int>pli;
typedef pair<ll,ll>pll;
typedef pair<int,ll>pil;
typedef vector<int>vi;
typedef vector<ll>vll;
typedef vector<pii>vpii;
typedef vector<pil>vpil;
template<typename T>T cmax(T &x, T y){return x=x>y?x:y;}
template<typename T>T cmin(T &x, T y){return x=x<y?x:y;}
template<typename T>
T &read(T &r){
	r=0;bool w=0;char ch=getchar();
	while(ch<'0'||ch>'9')w=ch=='-'?1:0,ch=getchar();
	while(ch>='0'&&ch<='9')r=r*10+(ch^48),ch=getchar();
	return r=w?-r:r;
}
template<typename T1,typename... T2>
void read(T1 &x,T2& ...y){read(x);read(y...);}
const int inf=0x7fffffff;
const int N=200010;
int weektoday(int x,int y){
	return x*7+y;
}
map<string,int>xingqi;//星期几 -> number 
int n,m,k;
int rel[N];
set<int>ren[N];//人 星期几工作 
set<int>ban[8];//星期几   ban掉第几周 
int prl[N];
vi pro[N];//project
int jd[N];//进度
int ans[N];
//----------------------------------------------
int week=-1,lastxq=7;
int nxtw[8];//next week
int Nxt(int o){
	cmax(nxtw[o],week);
	if(ban[o].empty())return nxtw[o];
	while(nxtw[o]>(*ban[o].begin()))ban[o].erase(ban[o].begin());
	while(nxtw[o]==(*ban[o].begin()))ban[o].erase(ban[o].begin()),++nxtw[o];
	return nxtw[o];
}
//----------------------------------------------
set<int>sren[8];//星期几  有工作在身的人 
priority_queue<int,vector<int>,greater<int>>que[N];//每个人要完成的project
vpii GX;//第p个人要做第x个任务 
int nowday;
void Jin(int x){
//	dpi(week,lastxq);
	++jd[x];
	if(jd[x]<prl[x]){
		int p=pro[x][jd[x]];
		GX.pb(mp(p,x));
	}
	if(jd[x]==prl[x]){
		ans[x]=nowday;
	}
}
bool chk(int p,int x){//检查x目前是否是需要p来完成 
	if(jd[x]==prl[x])return 0;
	return pro[x][jd[x]]==p;
}
int Gongzuo(int p){//让p工作 并且 返回是否还有任务 
	while(!que[p].empty()){
		int x=que[p].top();
		if(!chk(p,x))que[p].pop();
		else break;
	}
	if(!que[p].empty()){
		int x=que[p].top();que[p].pop();
		Jin(x);
	}
	return !que[p].empty();
}
void Gengxin(){
	for(auto i:GX){
		int p=i.fi,x=i.se;
		if(que[p].empty()){
			for(auto j:ren[p]){
				sren[j].insert(p);
			}
		}
		que[p].push(x);
	}
	vpii().swap(GX);
}
signed main(){
    #ifdef do_while_true
//    	assert(freopen("data.in","r",stdin));
	#endif
	//"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday".
	xingqi["Monday"]=1;
	xingqi["Tuesday"]=2;
	xingqi["Wednesday"]=3;
	xingqi["Thursday"]=4;
	xingqi["Friday"]=5;
	xingqi["Saturday"]=6;
	xingqi["Sunday"]=7;
	read(n,m,k);
	for(int i=1;i<=n;i++){
		read(rel[i]);
		for(int j=1;j<=rel[i];j++){
			string str;
			cin >> str;
			ren[i].insert(xingqi[str]);
		}
	}
	for(int i=1;i<=m;i++){
		int x;read(x);
		ban[(x-1)%7+1].insert((x-1)/7);
	}
	for(int i=1;i<=k;i++){
		read(prl[i]);
		for(int j=1;j<=prl[i];j++){
			int x;read(x);
			pro[i].pb(x);
		}
	}
	for(int i=1;i<=k;i++){
		jd[i]=-1;
		Jin(i);
		Gengxin();
	}
//	int qwq=0;
	do{
//		++qwq;
//		dbg(qwq);
		static int mnd[8];
		static int pos[8];
		vi vec;
		for(int i=lastxq+1;i<=7;i++)mnd[i]=weektoday(Nxt(i),i);
		++week;
		for(int i=1;i<=lastxq;i++)mnd[i]=weektoday(Nxt(i),i);
		--week;
		for(int i=1;i<=7;i++)pos[i]=i;
		sort(pos+1,pos+7+1,[&](const int &x,const int &y){return mnd[x]<mnd[y];});
		bool fl=0;
		for(int i=1;i<=7;i++){
			int o=pos[i];
			if(sren[o].empty())continue;
			lastxq=o;
			nowday=mnd[pos[i]];
			week=(nowday-1)/7;
			vi peo;
			for(auto p:sren[o])peo.pb(p);
			for(auto p:peo){
				if(!Gongzuo(p)){
					sren[o].erase(p);
				}
			}
			Gengxin();
			fl=1;
			break;
		}
		if(!fl)break;
	}while(true);
	for(int i=1;i<=k;i++)cout << ans[i] << ' ';
    #ifdef do_while_true
//		cerr<<'\n'<<"Time:"<<1.0*clock()/CLOCKS_PER_SEC*1000<<" ms"<<'\n';
	#endif
	return 0;
}
posted @ 2022-11-28 23:02  do_while_true  阅读(41)  评论(0编辑  收藏  举报