Educational Codeforces Round 10

文章目录

    • A. Gabriel and Caterpillar
    • B. z-sort
    • C. Foe Pairs
    • D. Nested Segments
    • E. Pursuit For Artifacts

EDU10,C,D,E,典中典。

A. Gabriel and Caterpillar

思路:硬模拟即可。

#include 

using namespace std;
const int N = 2e6 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
// #define endl "\n"

void solve()
{	
	int h1,h2;
	cin>>h1>>h2;
	int a,b;
	cin>>a>>b;
	if(h1+8*a>=h2){
		cout<<0<<endl;
		return ;
	}
	int day=1;
	int x;
	if(a<=b){
		cout<<-1<<endl;
		return ;
	}
	h1+=8*a-12*b;
	if(h1+a*12>=h2){
		cout<<day<<endl;
		return ;
	}
	x=h2-h1-a*12;
	cout<<day+(x+(a-b)*12-1)/((a-b)*12)<<endl;
}

int main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	t=1;
	//cin>>t;
	while(t--){
		solve();
	}
    system("pause");
    return 0;
}

B. z-sort

思路:排序后奇偶对调即可,不存在不合法的情况。

#include 

using namespace std;
const int N = 2e6 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
// #define endl "\n"

void solve()
{	
	int n;
	cin>>n;
	vector<int> a(n+5);
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a.begin()+1,a.begin()+1+n);
	for(int i=2;i+1<=n;i+=2){
		swap(a[i],a[i+1]);
	}
	int f=1;
	for(int i=1;i<=n;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;
}

int main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	t=1;
	//cin>>t;
	while(t--){
		solve();
	}
    system("pause");
    return 0;
}

C. Foe Pairs

很经典的一道计算贡献的题目。
对于计算贡献区间的题目,我们一般有两种处理方法:
第一种就是固定左端点,去枚举右端点;
第二种就是考虑对于二进制类型的贡献问题,我们将每个数字进行拆位,考虑该数二进制表示下每一位的贡献。

思路:很显然,因为要考虑所有区间对答案的贡献,所以我们思考,对于每一个左端点,是否能求出其能延申的最远距离,即最大合法右端点,我们对限制条件进行处理,即对于给定数对 [ a , b ] [a,b] [a,b], a a a所在的下标 i i i是无法延申到 b b b所在的下标 j j j的,最后按此维护一下最大后缀即可,因为我们顺着来无法退出第 i i i个数最远能够延申到哪,因为只有第 i + 1 i+1 i+1个数确定了其延申范围,我们才能对 i i i进行更新。(因为不会出现第 i + 1 i+1 i+1能到达 j j j,但 i i i无法到达 j j j的情况)。

#include 

using namespace std;
const int N = 2e6 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
// #define endl "\n"

void solve()
{	
	int n,m;
	cin>>n>>m;
	vector<int> a(n+5),st(n+5);
	for(int i=1;i<=n;i++) cin>>a[i],st[a[i]]=i;
	vector<int> l(n+5,n),r(n+5);
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		int xi=st[x],yi=st[y];
		if(xi>yi) swap(xi,yi);
		l[xi]=min(l[xi],yi-1);
	}
	l[n+1]=n+1;
	for(int i=n-1;i>=1;i--){ 
		l[i]=min(l[i+1],l[i]);
	}
	ll sum=0;
	for(int i=1;i<=n;i++){
		ll x=l[i]-i+1;
		sum+=x;
	}
	cout<<sum<<endl;
}

int main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	t=1;
	//cin>>t;
	while(t--){
		solve();
	}
    system("pause");
    return 0;
}

D. Nested Segments

又是典中典,经典二维偏序问题,对于给定线段 [ l , r ] [l,r] [l,r],我们要找到在 [ l , r ] [l,r] [l,r]范围内的线段数,那么可以将 l , r l,r l,r转化为二维坐标系中的一个点,然后我们对所有点按照x轴进行排序,此题就转化为了,对于给定的点 ( l , r ) (l,r) (l,r),横坐标比他大,但纵坐标比他小的点有多少个,又因为我们是对横坐标进行排序,那么我们限制我们只需要从横坐标最大的点开始,使用一个数据结构去维护,对于每个点,有多少个点的纵坐标自身小即可。每遍历完一个点,我们就将该点放入数据结构中即可。
上述过程,我们很容易想到使用树状数组即可对上述内容进行维护。
注意该题数据范围为1e9,所以需要先进行离散化。

#include 

using namespace std;
const int N = 2e6 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
// #define endl "\n"

struct MIT//树状数组
{
ll tr[N];
int lowbit(int x) {
    return x & (-x);
}

void add(int u, int v) {
    for (int i = u; i < N; i += lowbit(i)) {
        tr[i] += v;
    }
}

ll query(int x) {
    ll res = 0;

    for (int i = x; i > 0; i -= lowbit(i)) {
        res += tr[i];
    }

    return res;
}
};
MIT c;
void solve()
{	

	int n;
	cin>>n;
	vector<p3> se(n+5);
	for(int i=1;i<=n;i++){
		int l,r;
		cin>>l>>r;
		se[i]={l,r,i};//因为要进行离散化,所以需要储存编号
	}
	sort(se.begin()+1,se.begin()+1+n,[](p3 x,p3 y){
		return x[0]>y[0];
	});
	vector<int> g(n+5);
	for(int i=1;i<=n;i++){
		auto [x,y,z]=se[i];
		g[i]=y;
	}
	sort(g.begin()+1,g.begin()+1+n);
	for(int i=1;i<=n;i++){
		int t=lower_bound(g.begin()+1,g.begin()+1+n,se[i][1])-g.begin();//经典离散化操作
		se[i][1]=t;//第二维才是我们需要的值
	}
	vector<int> ans(n+5);
	for(int i=1;i<=n;i++){//对每个点进行遍历
		auto [x,y,z]=se[i];
		int res=c.query(y);
		ans[z]=res;
		c.add(y,1);
	}
	for(int i=1;i<=n;i++) cout<<ans[i]<<endl;
}

int main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	t=1;
	//cin>>t;
	while(t--){
		solve();
	}
    system("pause");
    return 0;
}

E. Pursuit For Artifacts

还是典中典。
很明显的无向图,要求一条路只能通过一遍,标准的缩点提示。
思路:缩点后看从 a − b a-b ab的路径上是否存在边权为 1 的边即可。

#include 

using namespace std;
const int N = 2e6 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 1e9+7;
const int maxv = 4e6 + 5;
// #define endl "\n"

int n,m;
struct node
{
	int a,b,w;
}z[N];

vector<pll> e[N];
vector<pll> e2[N];
vector<vector<int> > vdcc;
int dfsn[N],low[N],tot,b[N];
stack<int> s;
void add(int u,int v,int i)
{
	e[u].push_back({v,i});
	e[v].push_back({u,i});
}

void tarjan(int x,int f)//tarjan缩点,跑出来所有的边双连通分量
{
	dfsn[x]=low[x]=++tot,s.push(x);
	for(auto [u,i]: e[x]){
		if(!dfsn[u]){
			tarjan(u,i);
			low[x]=min(low[x],low[u]);
		}
		else if(f!=i) low[x]=min(low[x],dfsn[u]);
	}
	if(dfsn[x]==low[x]){
		vector<int> c;
		while(1){
			auto t=s.top();
			b[t]=vdcc.size();
			c.push_back(t);
			s.pop();
			if(t==x) break;
		}
		vdcc.push_back(c);
	}
}
int st,ed;
int val[N];
int ans;
void dfs(int x,int f,int ans)//记录ans,
{
	if(x==ed){
		if(ans){
			cout<<"YES"<<endl;
		}
		else cout<<"NO"<<endl;
		return ;
	}
	for(auto [u,w]: e2[x]){
		if(u!=f) dfs(u,x,ans|w|val[u]);
	}
}


void solve()
{	
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,i);
		z[i]={u,v,w};
	}
	cin>>st>>ed;
	for(int i=1;i<=n;i++){
		if(!dfsn[i]){
			tarjan(i,-1);
		}
	}
	for(int i=1;i<=m;i++){//缩点过程
		auto [u,v,w]=z[i];
		if(b[u]!=b[v]){
			e2[b[u]].push_back({b[v],w});
			e2[b[v]].push_back({b[u],w});
		}
		else{//如果当前点在一个连通分量里面,我们就把当前连通分量和w与一下,因为如果当前权值为1,整个连通分量又可以相互到达,所以该连通分量的权值就为1.
			val[b[u]]|=w;
		}
	}
	st=b[st],ed=b[ed];
	ans=val[st];
	dfs(st,-1,ans);
}

int main()
{
    ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	t=1;
	//cin>>t;
	while(t--){
		solve();
	}
    system("pause");
    return 0;
}

你可能感兴趣的:(cf补题,算法,c++,数据结构)