2019.11.23日常总结

一本通P1519题解

【题意】: 根据宪法, B y t e l a n d Byteland 民主共和国的公众和平委员会应该在国会中通过立法程序来创立。 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。

此委员会必须满足下列条件:

每个党派都在委员会中恰有 1 1 个代表,

如果 2 2 个代表彼此厌恶,则他们不能都属于委员会。

每个党在议会中有 2 2 个代表。代表从 1 1 编号到 2 × n 2\times n 。 编号为 2 × i 1 2\times i−1 2 × i 2\times i 的代表属于第 i i 个党派。

任务:写一程序读入党派的数量和关系不友好的代表对,计算决定建立和平委员会是否可能,若行,则列出委员会的成员表。

【思路】: 2 s a t 2-sat 算法的模板题。我们记 p a r t n e r [ i ] partner[i] i i 的队友,考虑如果 ( u , v ) (u,v) 有矛盾,我们从 u u 连一条边到 p a r t n e r [ v ] partner[v] ,从 v v 连一条边到 p a r t n e r [ u ] partner[u] 。然后,直接跑一遍 t a r j a n tarjan 算法,如果 v v p a r t n e r [ v ] partner[v] 属于同一个强联通分量,则输出NIE,否则有解。
【代码】:

#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
	char c=0;int x=0;bool f=0;
	while (!g(c)) f=c=='-',c=gc;
	while (g(c)) x=x*10+c-48,c=gc;
	return f?-x:x;
}
const int N=16100,M=40100;
struct node{
	int next,to;
}e[M];int h[N],tot;
inline void add(int a,int b){
	e[++tot]=(node){h[a],b};h[a]=tot;
}
int dfscnt,dfn[N],low[N];
int Stack_top,Stack[N];
int belong[N],col,num[N];
void tarjan(int u){
	dfn[u]=low[u]=++dfscnt;
	Stack[++Stack_top]=u;
	for(int i=h[u];i;i=e[i].next){
		register int to=e[i].to;
		if (dfn[to]==0){
			tarjan(to);
			low[u]=min(low[u],low[to]);
		}
		else if (!belong[to])
			low[u]=min(low[u],dfn[to]);
	}
	if (low[u]==dfn[u]){
		belong[u]=++col;num[col]=1;
		while (Stack[Stack_top]!=u){
			int v=Stack[Stack_top];
			belong[v]=col;num[col]++;
			--Stack_top;
		}
		--Stack_top;
	}
}
int partner[N],n,m;
inline void read_the_data(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		partner[i*2-1]=i*2;
		partner[i*2]=i*2-1;
	}
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		add(u,partner[v]);
		add(v,partner[u]);
	}
}
inline void print_answer(){
	for(int i=1;i<=n;i++)
		if (belong[i*2]==belong[i*2-1]){
			printf("NIE");
			return;
		}
	for(int i=1;i<=2*n;i+=2)
		if (belong[i]>belong[partner[i]])
			printf("%d\n",partner[i]);
		else printf("%d\n",i);
}
inline int hpwwzyy2012(){
	read_the_data();
	for(int i=1;i<=2*n;i++)
		if (!dfn[i])
			tarjan(i);
	print_answer();
	return 0;
}
int main(){
	return hpwwzyy2012();
}

洛谷P3088

【题意】: F J FJ N ( 1 N 50 , 000 ) N(1 \leq N \leq 50,000) 头奶牛沿着一维的栅栏吃草,第 i i 头奶牛在目标点 x i x_i ,它的身高是 h i h_i ( 1 x i , h i 1 , 000 , 000 , 000 ) (1 \leq x_i,h_i \leq 1,000,000,000)。

当一头奶牛左边 D D 距离内而且右边 D D 距离内有身高至少是它的两倍的奶牛, ( 1 D 1 , 000 , 000 , 000 ) (1 \leq D \leq 1,000,000,000) ,它就会觉得拥挤。

请计算觉得拥挤的奶牛的数量。

【思路】: 首先,把牛按位置从小到大排序,然后进行计算。
考虑第 i i 头牛是否感觉拥挤。如果奶牛感觉拥挤,代表 [ h i D , h i ] [h_i-D,h_i] 中牛的身高 2 × x i \geq 2 \times x_i ,等同于 [ h i D , h i ] [h_i-D,h_i] 中最高的牛的身高 2 × x i \geq 2 \times x_i ,所以我们可以用单调队列进行优化。
注意题目中说,左和右要有至少有一头牛的身高 2 × x i \geq 2 \times x_i ,所以分两部分,左和右,分别计算。当且仅当同时有解时,统计奶牛 i i 进答案。
【代码】:

#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
	char c=0;int x=0;bool f=0;
	while (!g(c)) f=c=='-',c=gc;
	while (g(c)) x=x*10+c-48,c=gc;
	return f?-x:x;
}
const int N=50100;
struct node{
	int location,height;
	void read_itself(){
		location=read();
		height=read();
	}
	bool operator < (node c) const{
		return location<c.location;
	}
}a[N];int q[N],h,t,n,D;
int feel_crowded[N];
inline void read_the_date(){
	n=read();D=read();
	for(int i=1;i<=n;i++)
		a[i].read_itself();
	sort(a+1,a+n+1);
}
inline void calc_answer(){
	h=1;t=0;q[1]=0;
	for(int i=1;i<=n;i++){
		while (h<=t&&a[q[h]].location<a[i].location-D) h++;
		while (h<=t&&a[q[t]].height<=a[i].height) t--;q[++t]=i;
		if (a[q[h]].height>=2*a[i].height) feel_crowded[i]++;
//		printf("i=%d,h=%d,t=%d\n",i,h,t);
	}
	h=1;t=0;memset(q,0,sizeof(q));
//	printf("------------\n");
	for(int i=n;i;i--){
		while (h<=t&&a[q[h]].location>a[i].location+D) h++;
		while (h<=t&&a[q[t]].height<=a[i].height) t--;q[++t]=i;
		if (a[q[h]].height>=2*a[i].height) feel_crowded[i]++;
//		printf("i=%d,h=%d,t=%d\n",i,h,t);
	}
}
inline void print_answer(){
	register int ans=0;
	for(int i=1;i<=n;i++)
		if (feel_crowded[i]==2){
//			printf("%d\n",i);
			ans++;
		}
	printf("%d",ans);
}
inline int HPXXZYY(){
	read_the_date();
	calc_answer();
	print_answer();
	return 0;
}
int main(){
//	freopen("t1.in","r",stdin);
	return HPXXZYY();
}
发布了82 篇原创文章 · 获赞 4 · 访问量 1785

猜你喜欢

转载自blog.csdn.net/ZHUYINGYE_123456/article/details/103218633
今日推荐