AtCoder Beginner Contest 216

\(\text{G - 01Sequence}\)

解法

\(x_i\) 为序列中 \([1,i]\) 之间 \(1\) 的个数。那么 \((l,r,x)\) 就可以转化成 \(x_r-x_{l-1}\ge x\)

由于我们需要求 \(x_n\) 的最小值,可以从 \(l-1\)\(r\) 连一条权值为 \(x\) 的边,求最长路。由于边权为正,所以不能用 \(\mathtt{Dijkstra}\)。但这题用 \(\mathtt{SPFA}\) 会被卡,那咋办捏?

不妨换一个角度:设 \(x_i\) 为序列中 \([1,i]\) 之间 \(0\) 的个数。那么 \((l,r,x)\) 就可以转化成 \(x_r-x_{l-1}\le r-l+1-x\)。此时正好要求 \(x_n\) 的最大值,就转化成了从 \(l-1\)\(r\) 连一条权值为 \(r-l+1-x\) 的边,求最短路。

另外还要注意一个条件:\(0\le x_{i+1}-x_i\le 1\)

代码

#include <cstdio>
#define print(x,y) write(x),putchar(y)

template <class T>
inline T read(const T sample) {
	T x=0; char s; bool f=0;
	while((s=getchar())>‘9‘ or s<‘0‘)
		f|=(s==‘-‘);
	while(s>=‘0‘ and s<=‘9‘)
		x=(x<<1)+(x<<3)+(s^48),
		s=getchar();
	return f?-x:x;
}

template <class T>
inline void write(const T x) {
	if(x<0) {
		putchar(‘-‘),write(-x);
		return;
	}
	if(x>9) write(x/10);
	putchar(x%10^48);
}

#include <queue>
#include <cstring>
using namespace std;

const int maxn=2e5+5;

struct node {
	int nxt,to,val;
} e[maxn*3];
struct Node {
	int x,v;
	
	bool operator < (const Node &t) const {
		return v>t.v;
	}
};
int n,m,cnt,head[maxn];
int d[maxn];
bool vis[maxn];
priority_queue <Node> q;

void addEdge(int u,int v,int w) {
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	e[cnt].val=w;
	head[u]=cnt;
}

void Dijkstra() {
	q.push((Node){0,0});
	memset(d,0x3f,sizeof d);
	d[0]=0;
	while(!q.empty()) {
		Node t=q.top(); q.pop();
		if(vis[t.x] or (t.v^d[t.x]))
			continue;
		vis[t.x]=1;
		for(int i=head[t.x];i;i=e[i].nxt) {
			int v=e[i].to;
			if(d[v]>d[t.x]+e[i].val) {
				d[v]=d[t.x]+e[i].val;
				q.push((Node){v,d[v]});
			}
		}
	}
}

int main() {
	n=read(9),m=read(9);
	int l,r,x;
	for(int i=1;i<=m;++i) {
		l=read(9),r=read(9);
		x=r-l+1-read(9);
		addEdge(l-1,r,x);
	}
	for(int i=0;i<n;++i)
		addEdge(i+1,i,0),
		addEdge(i,i+1,1);
	Dijkstra();
	for(int i=1;i<=n;++i)
		putchar(d[i]-d[i-1]^‘1‘),putchar(‘ ‘);
	puts("");
	return 0;
}

AtCoder Beginner Contest 216

上一篇:如何运用PHP+REDIS解决负载均衡后的session共享问题


下一篇:如何编写优雅的Dockerfile