CF1479C Continuous City 題解 [進制+構造]


Continuous City

Description:

​ Some time ago Homer lived in a beautiful city. There were n blocks numbered from \(1\) to \(n\) and \(m\) directed roads between them. Each road had a positive length, and each road went from the block with the smaller index to the block with the larger index. For every two (different) blocks, there was at most one road between them.

Homer discovered that for some two numbers \(L\) and \(R\) the city was \((L, R)-continuous\).

The city is said to be \((L, R)-continuous\), if

  1. all paths from block \(1\) to block \(n\) are of length between \(L\) and \(R\) (inclusive); and
  2. for every \(L \leq d \leq R\), there is exactly one path from block \(1\) to block \(n\) whose length is \(d\).

A path from block \(u\) to block \(v\) is a sequence \(u = x_0 \to x_1 \to x_2 \to \dots \to x_k = v\), where there is a road from block \(x_{i-1}\) to block \(x_{i}\) for every \(1 \leq i \leq k\). The length of a path is the sum of lengths over all roads in the path. Two paths \(x_0 \to x_1 \to \dots \to x_k\) and \(y_0 \to y_1 \to \dots \to y_l\) are different, if \(k \neq l\) or \(x_i \neq y_i\) for some \(0 \leq i \leq \min\{k, l\}\).

After moving to another city, Homer only remembers the two special numbers \(L\) and \(R\) but forgets the numbers \(n\) and \(m\) of blocks and roads, respectively, and how blocks are connected by roads. However, he believes the number of blocks should be no larger than \(32\) (because the city was small).

As the best friend of Homer, please tell him whether it is possible to find a \((L, R)-continuous\) city or not.

中文題面:

​ 給你兩個數 \(L,R\),構造一張DAG滿足從 \(1\)\(n\) 的所有路徑恰有 \(R-L+1\) 條 , 且路徑長度值域恰好為 \([L,R]\) 。構造的DAG的點數不超過\(32\),DAG的邊只能從小編號連向大編號.

Input:

​ The single line contains two integers \(L\) and \(R\) (\(1 \leq L \leq R \leq 10^6\)).

Output:

​ If it is impossible to find a \((L, R)-continuous\) city within \(32\) blocks, print "NO" in a single line.

​ Otherwise, print "YES" in the first line followed by a description of a \((L, R)-continuous\) city.

​ The second line should contain two integers \(n\) (\(2 \leq n \leq 32\)) and \(m\) (\(1 \leq m \leq \frac {n(n-1)} 2\)), where \(n\) denotes the number of blocks and \(m\) denotes the number of roads.

​ Then \(m\) lines follow. The i-th of the \(m\) lines should contain three integers \(a_i, b_i\) (\(1 \leq a_i < b_i \leq n\)) and \(c_i\) (\(1 \leq c_i \leq 10^6\)) indicating that there is a directed road from block \(a_i\) to block \(b_i\) of length \(c_i\).

​ It is required that for every two blocks, there should be no more than \(1\) road connecting them. That is, for every \(1 \leq i < j \leq m\), either \(a_i \neq a_j\) or \(b_i \neq b_j\).

Sample Input 1:

1 1

Sample Output 1:

YES
2 1
1 2 1

Sample Input 2:

4 6

Sample Output 2:

YES
5 6
1 2 3
1 3 4
1 4 5
2 5 1
3 5 1
4 5 1

Note:

​ In the first example there is only one path from block \(1\) to block \(n = 2\), and its length is \(1\).

​ In the second example there are three paths from block \(1\) to block \(n = 5\), which are \(1 \to 2 \to 5\) of length \(4\), \(1 \to 3 \to 5\) of length \(5\) and \(1 \to 4 \to 5\) of length \(6\).

Hint:

​ 時間限制: \(2s\)

​ 空間限制: \(512M\)

題目分析:

​ 構造題,首先要看數據范圍。我們發現 \(L,R\) 是能達到 \(2^{20}\) 級別的數,而 \(n \leq 32\) ,因此不難想到二進制拆分。具體怎么做我們需要循序漸進地考慮。

​ 1.如果 \(L=1,R=2^k\) :

\(k=0\) : 直接在 \(1\)\(n=2\) 之間連一條邊即可。

\(k>0\) :我們考慮構造 \(k+2\) 個點。假設第 \(i (2 \leq i \leq k + 1)\) 個點滿足 \((1, 2^{i-2})-continuous\) , 我們在 \(1\)\(k+2\) 之間連一條長度為 \(1\) 的邊,在 \(i (2 \leq i \leq k + 1)\)\(k+2\) 之間連一條長度為 \(2^{i-2}\) 的邊,此時就能滿足 \(k+2\)\((1, 2^{k})-continuous\)

​ 這種情況消耗的點數為 $ k+2 $ ,即 \(\log_2R\).

​ 2.如果 \(L=1\)

​ 先將 \(R-1\) 二進制拆分使得 \(R-1=\sum_{i=0}^{k} (p_i \times 2^{i})\).

​ 我們延續 \(1\) 的做法,先使用 $k+2 $ 個點滿足第 \(i (2 \leq i \leq k + 2)\) 個點滿足 \((1, 2^{i-2})-continuous\)

​ 接下來的做法非常重要——

​ 我們要構造第 \(k+3\) 個點滿足 \((1, R)-continuous\).

​ 我們先在 \(1\) 與 $ k+3 $ 之間連一條長度為 \(1\) 的邊,然后對於 $\forall 2 \leq i \leq k+2 $ ,如果 \(p_i=1\) ,在 \(i\)\(k+3\) 間連一條長度為 \(\sum_{j=i-1}^k (p_j \times 2^j)\) 的邊。

​ 此時滿足題意,消耗的點數為 \(k+3\) .

​ 3.如果\(L>1\):

​ 先在 \(1\)\(2\) 之間連一條長度為 \(L-1\) 的邊,剩下的部分同做法 \(2\) .

​ 此時消耗的點數為 \(k+4\)

​ 綜上,\(maxn = 23\).

​ PS:我的做法需要特判 \(L=R\).

​ 代碼如下(馬蜂很丑,不喜勿噴)——

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,m,p[maxn],a[maxn],b[maxn],c[maxn];
inline int read(){
	int ret=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) ret=(ret<<1)+(ret<<3)+ch-'0',ch=getchar();return ret*f;
}
int main(){
	puts("YES");int L=read(),R=read();
	if(L==R) cout<<2<<' '<<1<<'\n'<<1<<' '<<2<<' '<<L<<'\n',exit(0);
	if(L==1){
		int x=log2(R-1),sum=1;n=x+3;for(register int i=0;i<=x;i++) if((1<<i)&(R-1)) p[i]=1;
		for(register int i=0;i<=x;i++) a[++m]=1,b[m]=i+2,c[m]=1;
		for(register int i=0;i<x;i++) for(register int j=i+1;j<=x;j++) a[++m]=i+2,b[m]=j+2,c[m]=(1<<i);
		a[++m]=1,b[m]=n,c[m]=1;for(register int i=x;i>=0;i--) if(p[i]==1) a[++m]=i+2,b[m]=n,c[m]=sum,sum+=(1<<i);
		cout<<n<<' '<<m<<'\n';for(register int i=1;i<=m;i++) cout<<a[i]<<' '<<b[i]<<' '<<c[i]<<'\n';
	}
	else{
		a[++m]=1,b[m]=2,c[m]=L-1;int x=log2(R-L),sum=1;n=x+4;
		for(register int i=0;i<=x;i++) if((1<<i)&(R-L)) p[i+1]=1;
		for(register int i=1;i<=x+1;i++) a[++m]=2,b[m]=i+2,c[m]=1;
		for(register int i=1;i<=x;i++) for(register int j=i+1;j<=x+1;j++) a[++m]=i+2,b[m]=j+2,c[m]=(1<<(i-1));
		a[++m]=2,b[m]=n,c[m]=1;for(register int i=x+1;i;i--) if(p[i]==1) a[++m]=i+2,b[m]=n,c[m]=sum,sum+=(1<<(i-1));
		cout<<n<<' '<<m<<'\n';for(register int i=1;i<=m;i++) cout<<a[i]<<' '<<b[i]<<' '<<c[i]<<'\n';
	}
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM