【CF1146】Forethought Future Cup - Elimination Round
Forethought Future Cup - Elimination Round
窝也不知道这是个啥比赛QwQ
A. Love "A"
给你一个串,你可以删去若干个元素,使得最后
a的个数严格大于一半。求最大串长。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[55];int v=0,n;
int main()
{
	scanf("%s",s+1);n=strlen(s+1);
	for(int i=1;i<=n;++i)v+=(s[i]=='a');
	while(v*2<=n)--n;
	printf("%d\n",n);
	return 0;
}
B. Hate "A"
给你一个串\(s\),定义\(s'\)为\(s\)删去所有
a后的串,定义\(t=s+s'\)。
现在给你\(t\),你需要还原一组合法的\(s\)。
找到极大位置满足前面删去a之后的串长和后面相等,判断一下两个串是否相等就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 100100
char s[MAX],a[MAX];
int n,t;
void check(int p)
{
	for(int i=p;i<=n;++i)
		if(s[i]!=a[i-p+1])return;
	for(int i=1;i<p;++i)putchar(s[i]);
	puts("");exit(0);
}
int main()
{
	scanf("%s",s+1);n=strlen(s+1);
	for(int i=1;i<=n;++i)
	{
		if(s[i]!='a')a[++t]=s[i];
		if(n-i==t)check(i+1);
	}
	puts(":(");
	return 0;
}
C. Tree Diameter
交互题。
有一棵树,每次你可以询问两个集合,会告诉你从这两个集合中各取一个点的最大距离。现在你要求出树的直径。
询问次数不超过\(9\)次。
\(n\le 100\),边权不超过\(100\)。
我们只需要确定直径的一个端点,然后询问这个点到其他所有点的距离的最大值就行了。
一个很呆的想法是我们每次随机把点集分成两半,然后求一个最大值,但是这样子的正确率是\(\frac{1}{512}\),显然是不够的。
我们知道这样一个结论:距离树上某个点的最远点一定是直径的一个端点。
那么我们先对于\(1\)求出到其他所有点的最远距离,这样子对于剩余的点集进行二分就可以求出一个直径的端点,再询问一次就是答案啦。
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int Query(vector<int> &A,vector<int> &B)
{
	printf("%d %d ",A.size(),B.size());
	for(int v:A)printf("%d ",v);
	for(int v:B)printf("%d ",v);
	puts("");fflush(stdout);
	int x;scanf("%d",&x);
	return x;
}
int main()
{
	int T,n;scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		vector<int> A,B;
		A.push_back(1);
		for(int i=2;i<=n;++i)B.push_back(i);
		int now=Query(A,B);
		int l=0,r=n-2;
		while(l<r)
		{
			int mid=(l+r)>>1;
			vector<int> a,b;
			for(int i=0;i<=mid;++i)a.push_back(B[i]);
			for(int i=mid+1;i<n-1;++i)b.push_back(B[i]);
			if(Query(A,a)==now)r=mid;
			else l=mid+1;
		}
		int p=B[l];
		A.clear();B.clear();
		A.push_back(p);
		for(int i=1;i<=n;++i)if(i!=p)B.push_back(i);
		printf("-1 %d\n",Query(A,B));fflush(stdout);
	}
	return 0;
}
D. Frog Jumping
有一只青蛙,初始时在\(0\)位置,每次可以沿数轴正方向跳\(a\)个单位或者是沿着负方向跳\(b\)个单位。
定义\(f(x)\)为在不跳出区间\([0,x]\)的情况下,能够跳到的位置个数。
求\(\sum_{i=0}^m f(i)\)。
\(a,b\le 10^5,m\le 10^9\)。
先来看看\(f(n)\)怎么求,大力猜想一下一定能够从\(f(n-a)\)转移过来,然后再考虑一下中间这\(a\)步能够走到些什么地方,大力猜猜可以走到所有\((n-a)+gcd(a,b)\)倍数的位置,所以大力猜想一下\(f(n+a)=f(n)+\frac{a}{gcd(a,b)}\)。
然而这样子在\(n\)很小的时候肯定是假的,估摸一下\(n\ge a+b\)的时候是真的,其他时候是假的。
但是\(a+b\le 2*10^5\),所以我们可以考虑大力暴力计算一下答案。
怎么算呢?设\(f[i]\)表示经过不超过最小的\(f[i]\)可以到达\(i\)位置。这个东西显然就是一个最短路的问题,跑一遍\(dijkstra\)就可以算出来。
剩下的就是一个简单的计算问题啦。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define pi pair<ll,int>
#define mp make_pair
#define MAX 1000000
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
ll dis[MAX],f[MAX];
bool vis[MAX];
int m,a,b,N;
priority_queue<pi,vector<pi>,greater<pi> >Q;
int main()
{
	m=read();a=read();b=read();N=a+a+b;
	memset(dis,63,sizeof(dis));
	dis[0]=0;Q.push(mp(0,0));
	while(!Q.empty())
	{
		int u=Q.top().second;Q.pop();
		if(vis[u])continue;vis[u]=true;
		if(u>=b&&dis[u-b]>dis[u])dis[u-b]=dis[u],Q.push(mp(dis[u-b],u-b));
		if(u+a<=N&&dis[u+a]>max(0ll+u+a,dis[u]))dis[u+a]=max(0ll+u+a,dis[u]),Q.push(mp(dis[u+a],u+a));
	}
	ll ans=0;int mm=min(m,a+b-1);
	for(int i=0;i<=N;++i)
		if(dis[i]<=N)f[dis[i]]+=1;
	for(int i=1;i<=N;++i)f[i]+=f[i-1];
	for(int i=0;i<=mm;++i)ans+=f[i];
	if(m>=a+b)
	{
		int d=a/__gcd(a,b);
		for(int i=a+b,j=0;j<a&&i<=m;++j,++i)
		{
			int L=(m-i)/a;
			ans+=(L+1)*f[i]+1ll*L*(L+1)/2*d;
		}
	}
	printf("%lld\n",ans);
	return 0;
}
E. Hot is Cold
一开始有一个数列,你要执行\(n\)次操作,每次给你一个\(>x\)或者\(<x\),如果一个数带进去合法,就把他变成相反数,求出最后的数列。
\(n,Q\le 2*10^5,-10^5\le a_i\le 10^5\)
显然只需要对于每个值算答案最后再询问就好了。
那么拿一个线段树维护值域,记录每个值是否被翻转过。
那么每次大力讨论,发现只需要维护区间赋值和区间翻转就行了。
注意这里是\(<\)和\(>\),所以要特殊处理一下\(x\)和\(-x\)这两个位置。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 200200
#define lson (now<<1)
#define rson (now<<1|1)
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
int t[MAX<<2],tag[MAX<<2],rev[MAX<<2];
void puttag(int now,int v){t[now]=tag[now]=v;rev[now]=0;}
void putrev(int now){t[now]^=1;rev[now]^=1;}
void pushdown(int now)
{
	if(~tag[now])
	{
		puttag(lson,tag[now]);
		puttag(rson,tag[now]);
		tag[now]=-1;
	}
	if(rev[now])
	{
		putrev(lson);putrev(rson);
		rev[now]=0;
	}
}
void Modify(int now,int l,int r,int L,int R,int w)
{
	if(L>R)return;
	if(L<=l&&r<=R){puttag(now,w);return;}
	int mid=(l+r)>>1;pushdown(now);
	if(L<=mid)Modify(lson,l,mid,L,R,w);
	if(R>mid)Modify(rson,mid+1,r,L,R,w);
}
void Modify(int now,int l,int r,int L,int R)
{
	if(L>R)return;
	if(L<=l&&r<=R){putrev(now);return;}
	int mid=(l+r)>>1;pushdown(now);
	if(L<=mid)Modify(lson,l,mid,L,R);
	if(R>mid)Modify(rson,mid+1,r,L,R);
}
int Query(int now,int l,int r,int p)
{
	if(l==r)return t[now];
	int mid=(l+r)>>1;pushdown(now);
	if(p<=mid)return Query(lson,l,mid,p);
	else return Query(rson,mid+1,r,p);
}
int n,Q,x,a[MAX];char ch[MAX];
const int N=1e5;
int main()
{
	n=read();Q=read();
	for(int i=1;i<=n;++i)a[i]=read();
	memset(tag,-1,sizeof(tag));
	while(Q--)
	{
		scanf("%s",ch);x=read();
		if(ch[0]=='>')
		{
			if(x>=0)Modify(1,-N,N,x+1,N,1),Modify(1,-N,N,-N,-x-1,0);
			else
			{
				Modify(1,-N,N,x+1,-x-1),Modify(1,-N,N,-x+1,N,1),Modify(1,-N,N,-N,x-1,0);
				if(!Query(1,-N,N,-x))Modify(1,-N,N,-x,-x);
				if(Query(1,-N,N,x))Modify(1,-N,N,x,x);
			}
		}
		else
		{
			if(x<=0)Modify(1,-N,N,-N,x-1,1),Modify(1,-N,N,-x+1,N,0);
			else
			{
				Modify(1,-N,N,-x+1,x-1),Modify(1,-N,N,-N,-x-1,1),Modify(1,-N,N,x+1,N,0);
				if(!Query(1,-N,N,-x))Modify(1,-N,N,-x,-x);
				if(Query(1,-N,N,x))Modify(1,-N,N,x,x);
			}
		}
	}
	for(int i=1;i<=n;++i)printf("%d ",Query(1,-N,N,a[i])?-a[i]:a[i]);
	puts("");return 0;
}
F. Leaf Partition
给你一棵树,你要把叶子节点分成若干个集合,使得每个集合的\(f(S)\)都无交集。\(f(S)\)为最小的连通图使得所有\(S\)中的叶子节点都被连通。
求划分的方案数。
\(n\le 2*10^5\)
设\(f[i][0/1/2]\)表示当前考虑以\(i\)为根的子树,\(0\)表示当前点不会被划分到任何一个集合中,\(1\)表示和\(1\)个儿子相连,\(2\)表示和两个以上的儿子相连,转移就很简单了。
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define MAX 200200
#define MOD 998244353
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
int n,f[MAX][3];
vector<int> E[MAX];
void dfs(int u)
{
	if(E[u].empty())f[u][2]=1;else f[u][0]=1;
	for(int v:E[u])
	{
		dfs(v);
		f[u][2]=(1ll*f[u][2]*(f[v][0]+f[v][2])+1ll*(f[u][1]+f[u][2])*(f[v][1]+f[v][2]))%MOD;
		f[u][1]=(1ll*f[u][1]*(f[v][0]+f[v][2])+1ll*f[u][0]*(f[v][1]+f[v][2]))%MOD;
		f[u][0]=1ll*f[u][0]*(f[v][0]+f[v][2])%MOD;
	}
}
int main()
{
	n=read();
	for(int i=2;i<=n;++i)E[read()].push_back(i);
	dfs(1);printf("%d\n",(f[1][0]+f[1][2])%MOD);
	return 0;
}
G. Zoning Restrictions
一个人要在一条路上修\(n\)栋高度为\([0,h]\)的房子,假设修了一栋高度为\(a\)的房子就会产生收益\(a^2\)。有\(m\)个限制,每个限制\([l,r],x,c\),即在\([l,r]\)这些房子中,如果最高的房子严格大于了\(x\),就要交\(c\)的罚款。
求最大收益。
\(n,h,m\le 50\)
简单网络流?
先把每个点拆成\(h+1\)个点,然后串起来,连边为选择\(a\)时减少的代价。
对于一个限制\([l,r]\),把对应的第\(x+1\)个点和一个新点连起来,边权为\(inf\),再把新点和\(T\)相连,代价为罚款的值。
然后\(n*h*h\)减去最大流就是答案了。
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define MAX 3000
const int inf=1e9;
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
struct Line{int v,next,w;}e[1000000];
int h[MAX],cnt=2;
inline void Add(int u,int v,int w)
{
	e[cnt]=(Line){v,h[u],w};h[u]=cnt++;
	e[cnt]=(Line){u,h[v],0};h[v]=cnt++;
}
int S,T;
int level[MAX];
bool bfs()
{
	for(int i=S;i<=T;++i)level[i]=0;
	queue<int> Q;Q.push(S);level[S]=1;
	while(!Q.empty())
	{
		int u=Q.front();Q.pop();
		for(int i=h[u];i;i=e[i].next)
			if(!level[e[i].v]&&e[i].w)
				level[e[i].v]=level[u]+1,Q.push(e[i].v);
	}
	return level[T];
}
int dfs(int u,int flow)
{
	if(u==T||!flow)return flow;
	int ret=0;
	for(int i=h[u];i;i=e[i].next)
	{
		int v=e[i].v,d;
		if(level[v]==level[u]+1)
		{
			d=dfs(v,min(flow,e[i].w));
			ret+=d;flow-=d;
			e[i].w-=d;e[i^1].w+=d;
		}
	}
	return ret;
}
int Dinic()
{
	int ret=0;
	while(bfs())ret+=dfs(S,inf);
	return ret;
}
int a[55][55],tot,ans;
int n,H,m;
int main()
{
	n=read();H=read();m=read();
	S=0;T=n*(H+1)+m+1;ans=n*H*H;
	for(int i=1;i<=n;++i)
		for(int j=0;j<=H;++j)a[i][j]=++tot;
	for(int i=1;i<=n;++i)Add(S,a[i][0],inf);
	for(int i=1;i<=n;++i)
		for(int j=0;j<H;++j)
			Add(a[i][j],a[i][j+1],H*H-j*j);
	while(m--)
	{
		int l=read(),r=read(),x=read(),c=read();
		if(x==H)continue;++x;++tot;
		for(int i=l;i<=r;++i)Add(a[i][x],tot,inf);
		Add(tot,T,c);
	}
	printf("%d\n",ans-Dinic());
	return 0;
}
H. Satanic Panic
平面上有一堆点,你要求五角星的数量,保证不存在三点共线。
\(n\le 300\)。
本质上就是求五个点的凸包数量,也就是要找五条极角序递增的边。
把所有边按照极角序排序。
设\(f[i][j][1..5]\)表示从\(i\)点出发,当前到了\(j\),且中间确定了\(1..5\)条边的方案数。
每次新增一条边进来转移。
时间复杂度\(O(n^3)\)。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 330
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
struct Node{int x,y;}p[MAX];
Node operator-(Node a,Node b){return (Node){a.x-b.x,a.y-b.y};}
Node operator+(Node a,Node b){return (Node){a.x+b.x,a.y+b.y};}
ll Cross(Node a,Node b){return 1ll*a.x*b.y-1ll*b.x*a.y;}
bool operator<(Node a,Node b){return Cross(a,b)<0;}
struct Line{Node v;int a,b;};
bool operator<(Line a,Line b)
{
	if(a.v<b.v)return true;
	if(b.v<a.v)return false;
	if(a.a!=b.a)return a.a<b.a;
	return a.b<b.b;
}
int n;
vector<Line> E;
ll f[MAX][MAX][6];
int main()
{
	n=read();
	for(int i=1;i<=n;++i)p[i].x=read(),p[i].y=read();
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			if(i!=j)E.push_back((Line){(Node){p[j]-p[i]},i,j});
	sort(E.begin(),E.end());
	for(auto a:E)
	{
		int u=a.a,v=a.b;
		f[u][v][1]+=1;
		for(int i=1;i<=5;++i)
			for(int j=1;j<=n;++j)
				f[j][v][i+1]+=f[j][u][i];
	}
	ll ans=0;
	for(int i=1;i<=n;++i)ans+=f[i][i][5];
	printf("%lld\n",ans);
	return 0;
}
【CF1146】Forethought Future Cup - Elimination Round的更多相关文章
- CF1146 Forethought Future Cup Elimination Round Tutorial
		CF1146 Forethought Future Cup Elimination Round Tutorial 叮,守夜冠军卡 https://codeforces.com/blog/entry/6 ... 
- Forethought Future Cup - Elimination Round
		A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long char getc(){char c=get ... 
- Forethought Future Cup - Elimination Round D 贡献 + 推公式 + 最短路 + 贪心
		https://codeforces.com/contest/1146/problem/D 题意 有一只青蛙,一开始在0位置上,每次可以向前跳a,或者向后跳b,定义\(f(x)\)为青蛙在不跳出区间[ ... 
- Forethought Future Cup - Elimination Round C 二分 + 交互(求树的直径)
		https://codeforces.com/contest/1146/problem/C 题意 一颗大小为n的树,每次可以询问两个集合,返回两个集合中的点的最大距离,9次询问之内得出树的直径 题解 ... 
- Codeforces Forethought Future Cup Elimination Round  选做
		1146C Tree Diameter 题意 交互题.有一棵 \(n(n\le 100)\) 个点的树,你可以进行不超过 \(9\) 次询问,每次询问两个点集中两个不在同一点集的点的最大距离.求树的直 ... 
- 【动态规划】【滚动数组】【搜索】Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) D. Field expansion
		显然将扩张按从大到小排序之后,只有不超过前34个有效. d[i][j]表示使用前i个扩张,当length为j时,所能得到的最大的width是多少. 然后用二重循环更新即可, d[i][j*A[i]]= ... 
- Codeforces Round #557 Div. 1 based on Forethought Future Cup - Final Round
		A:开场就读错题.读对了之后也没啥好说的. #include<bits/stdc++.h> using namespace std; #define ll long long #defin ... 
- Forethought Future Cup - Final Round (Onsite Finalists Only) C. Thanos Nim 题解(博弈+思维)
		题目链接 题目大意 给你n堆石子(n为偶数),两个人玩游戏,每次选取n/2堆不为0的石子,然后从这n/2堆石子中丢掉一些石子(每一堆丢弃的石子数量可以不一样,但不能为0),若这次操作中没有n/2堆不为 ... 
- 【LibreOJ】#539. 「LibreOJ NOIP Round #1」旅游路线
		[题意]给定正边权有向图,车油量上限C,每个点可以花费pi加油至min(C,ci),走一条边油-1,T次询问s点出发带钱q,旅行路程至少为d的最多剩余钱数. n<=100,m<=1000, ... 
随机推荐
- C# 插入文本框到PPT幻灯片
			概述 在文本框中我们可以实现的操作有很多,如插入文字.图片.设置字体大小.颜色.文本框背景填充.边框设置等.下面的示例中,将介绍通过C# 在PPT幻灯片中插入幻灯片的方法. 示例中包含了以下要点: 插 ... 
- oracle学习笔记(一) oracle 体系结构简单介绍以及创建表空间和用户
			体系结构 oracle数据服务器由oracle数据库和实例组成 实例由后台进程和内存结构组成 内存结构由共享池,数据缓冲区,日志缓存区 Oracle数据库是通过表空间来存储物理表的,一个数据库实例可以 ... 
- Ubunttu16.04升级/更新git版本(亲测有效)
			sudo add-apt-repository ppa:git-core/ppa sudo apt-get update sudo apt-get install git 升级前: 升级后: 
- Python二级-----------程序冲刺2
			1. 编写 Python 程序输出一个具有如下风格效果的文本,用作文本进度条样式,部分代码如下,填写空格处. ... 
- 学习笔记—XML
			XML XML简介 XML指可扩展标记语言(EXtensible Markup Language),是一种标记语言. XML是一种灵活的语言,标签没有被预定义,需要自行定义标签. 通常,XML被用于信 ... 
- Android远程桌面助手之功能简介
			外国友人录制的ARDC的使用简介,非常不错,介绍得很详尽. 
- ngnix简单使用
			NGINX是一个高性能HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器,是由伊戈尔·塞索耶夫为俄罗斯访问量第二的Rambler.ru站点开发的,第一个公版发布于2004年10月4日 ... 
- Spark RPC框架源码分析(二)RPC运行时序
			前情提要: Spark RPC框架源码分析(一)简述 一. Spark RPC概述 上一篇我们已经说明了Spark RPC框架的一个简单例子,Spark RPC相关的两个编程模型,Actor模型和Re ... 
- Kubernetes 网络排错指南
			本文介绍各种常见的网络问题以及排错方法,包括 Pod 访问异常.Service 访问异常以及网络安全策略异常等. 说到 Kubernetes 的网络,其实无非就是以下三种情况之一 Pod 访问容器外部 ... 
- Python--day11(函数的参数)
			今日主要内容 1. 函数的参数 2. 函数的嵌套调用 1. 形参与实参 1. 参数介绍: 函数为什么要有参数:因为内部的函数体需要外部的数据 怎样定义函数的参数:在定义函数阶段,函数名在后面( ... 
