2019/2/28 考试记录

状态差得一批。。

T1

传送门

解题思路

  考试时想写\(60\)写挂。正解就是用堆把洗衣服的和晾衣服的贪心选一遍,求出每个衣服的最短时间,然后合并时就拿最大的和最小的,次大的和次小的依次合并取\(max\)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>

using namespace std;
const int N=100005;
typedef long long LL;

inline int rd(){
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return f?x:-x;
}

int n,m,l,w[N],d[N];
LL t1[N],t2[N],ans;
struct Node{
	int id; LL w;
	friend bool operator<(const Node A,const Node B){
		return A.w>B.w;
	}
	Node(int _id=0,LL _w=0) {id=_id; w=_w;}
};
priority_queue<Node> Q;

int main(){
	l=rd(),n=rd(),m=rd(); Node now;
	for(int i=1;i<=n;i++) w[i]=rd(),Q.push(Node(i,1ll*w[i]));
	for(int i=1;i<=l;i++){
		now=Q.top(); Q.pop();
		t1[i]=now.w; Q.push(Node(now.id,now.w+w[now.id]));
	}
	while(Q.size()) Q.pop();
	for(int i=1;i<=m;i++) d[i]=rd(),Q.push(Node(i,1ll*d[i]));
	for(int i=1;i<=l;i++){
		now=Q.top(); Q.pop();
		t2[i]=now.w; Q.push(Node(now.id,now.w+d[now.id]));
	}	
	for(int i=1;i<=l;i++) ans=max(ans,t1[i]+t2[l-i+1]);
	printf("%lld\n",ans);
	return 0;
}

T2

传送门

解题思路

  考场上暴搜\(20\)分。这个需要模型转化,首先说\(50\)分的做法,就是对于一个串来说,把它拆成两个,如果没有\('?'\)就拆成两个一样的,有的话拆的两个串一个把问号视作\(0\),一个视作\(1\),然后插到\(Trie\)树上。可以发现\(Trie\)树上一个节点和它的祖先不能同时存在,那么就转化成了个\(2-sat\)问题,可以暴力在树上跳,然后连边后\(2-sat\)判断,但这样连边边数过多,所以只有\(50\)分。而发现这样建边有好多无用的边,我们可以考虑优化连边,对于一个\(Trie\)上的点,我们可以把在这个点结束的串合并起来,然后建一个\(in\)\(out\),而对于\(2-sat\)里的边,发现对于一个点来说,它要连的其实就是这个节点中除自己的其他边,可以维护一个前缀后缀点的集合,这样边的数量就便少很多。

50分代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>

using namespace std;
const int N=1000005;

int n,head[N],cnt,to[N<<1],nxt[N<<1],pos[N];
char s[N];
vector<int> v[N];

void add(int bg,int ed){
//	cout<<bg<<" "<<ed<<endl;
	to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}

struct Trie{
	int ch[N][2],fa[N],tot=1;
	void build(int id){
		scanf("%s",s+1); int now=1,len=strlen(s+1);
		for(int i=1;i<=len;i++){
			if(s[i]=='?' || s[i]=='1') {
				if(ch[now][1]) now=ch[now][1];
				else ch[now][1]=++tot,fa[tot]=now,now=tot;
			}
			else {
				if(ch[now][0]) now=ch[now][0];
				else ch[now][0]=++tot,fa[tot]=now,now=tot;
			}
		} v[now].push_back(id); pos[id]=now; now=1;
		for(int i=1;i<=len;i++){
			if(s[i]=='1') {
				if(ch[now][1]) now=ch[now][1];
				else ch[now][1]=++tot,fa[tot]=now,now=tot;
			}
			else {
				if(ch[now][0]) now=ch[now][0];
				else ch[now][0]=++tot,fa[tot]=now,now=tot;	
			}
		}
		v[now].push_back(id+n); pos[id+n]=now;
	}
	void solve(int id){
		int now=pos[id],tmp;
		while(now!=1){
			for(int i=0;i<v[now].size();i++){
				tmp=v[now][i];
				if(tmp==id || tmp==id+n) continue;
				add(id,(tmp>n?tmp-n:tmp+n));
				add(tmp,(id>n?id-n:id+n));
			}
			now=fa[now];
		}	
	}
}trie;

int dfn[N],low[N],num,stk[N],top,col[N],col_num;
bool vis[N];

void tarjan(int x){
	dfn[x]=low[x]=++num; 
	stk[++top]=x; vis[x]=1;
	for(int i=head[x];i;i=nxt[i]){
		int u=to[i]; 
		if(!dfn[u]) tarjan(u),low[x]=min(low[x],low[u]);
		else if(vis[u]) low[x]=min(low[x],dfn[u]);
	}
	if(low[x]!=dfn[x]) return;
	col[x]=++col_num; vis[x]=0;
	while(stk[top]!=x){
		vis[stk[top]]=0;
		col[stk[top--]]=col_num;
	} top--;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) trie.build(i);
	for(int i=1;i<=2*n;i++) trie.solve(i);
	for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i);
	for(int i=1;i<=n;i++)
		if(col[i]==col[i+n]) {puts("NO"); return 0;}
	puts("YES");
	return 0;
}

100分代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>

using namespace std;
const int N=3000005;

int n,head[N],cnt,to[N<<3],nxt[N<<3],pos[N];
char s[N];
vector<int> v[N];

void add(int bg,int ed){
	to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}

inline int work(int id) {return id<=n?id+n:id-n;}

struct Trie{
	int ch[N][2],fa[N],tot=1,in[N],out[N];
	void build(int id){
		scanf("%s",s+1); int now=1,len=strlen(s+1);
		for(int i=1;i<=len;i++){
			if(s[i]=='?' || s[i]=='1') {
				if(ch[now][1]) now=ch[now][1];
				else ch[now][1]=++tot,fa[tot]=now,now=tot;
			}
			else {
				if(ch[now][0]) now=ch[now][0];
				else ch[now][0]=++tot,fa[tot]=now,now=tot;
			}
		} v[now].push_back(id); now=1;
		for(int i=1;i<=len;i++){
			if(s[i]=='1') {
				if(ch[now][1]) now=ch[now][1];
				else ch[now][1]=++tot,fa[tot]=now,now=tot;
			}
			else {
				if(ch[now][0]) now=ch[now][0];
				else ch[now][0]=++tot,fa[tot]=now,now=tot;	
			}
		}
		v[now].push_back(id+n);
	}
	void solve(){
		int tmp=tot; tot=n+n;
		for(int i=2;i<=tmp;i++){
			if(v[i].size()==0) continue;
			in[i]=++tot; out[i]=++tot;
			for(int j=0;j<v[i].size();j++){
				int x=v[i][j],y=work(v[i][j]);
				for(int k=fa[i];k;k=fa[k])
					if(in[k]) add(in[k],y),add(x,out[k]);
				add(x,in[i]); add(out[i],y);
			}
			static int w[N];
			for(int j=0;j<v[i].size();j++){
				int x=v[i][j]; w[j]=++tot;
				if(j) add(w[j],w[j-1]);
				add(w[j],work(x));
				int t=j-1;
				if(j && work(x)==v[i][j-1]) t--;
				if(t>=0) add(x,w[t]);
			}
			int num=v[i].size()-1;
			for(int j=num;j>=0;j--){
				int x=v[i][j]; w[j]=++tot;
				if(j<num) add(w[j],w[j+1]);
				add(w[j],work(x)); 
				int t=j+1;
				if(j<v[i].size()-1 && work(x)==v[i][j+1]) t++;
				if(t<v[i].size()) add(x,w[t]);
			}
		}	
	}	
}trie;

int dfn[N],low[N],num,stk[N],top,col[N],col_num;
bool vis[N];

void tarjan(int x){
	dfn[x]=low[x]=++num; 
	stk[++top]=x; vis[x]=1;
	for(int i=head[x];i;i=nxt[i]){
		int u=to[i]; 
		if(!dfn[u]) tarjan(u),low[x]=min(low[x],low[u]);
		else if(vis[u]) low[x]=min(low[x],dfn[u]);
	}
	if(low[x]!=dfn[x]) return;
	col[x]=++col_num; vis[x]=0;
	while(stk[top]!=x){
		vis[stk[top]]=0;
		col[stk[top--]]=col_num;
	} top--;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) trie.build(i);
	trie.solve();
	for(int i=1;i<=trie.tot;i++) if(!dfn[i]) tarjan(i);
	for(int i=1;i<=n;i++)
		if(col[i]==col[i+n]) {puts("NO"); return 0;}
	puts("YES");
	return 0;
}

T3

咕咕咕

posted @ 2019-02-28 21:01  Monster_Qi  阅读(161)  评论(0编辑  收藏  举报