【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, ...
随机推荐
- 在线生成二维码的API接口
现在很多大网站都有这样的一个功能,使用手机扫描一下网页上的二维码便可快速在手机上访问网站.想要实现这样的功能其实很简单,下面麦布分享几个在线生成网址二维码的API接口.都是采用http协议接口,无需下 ...
- Less与TypeScript的简单理解与应用,并使用WebPack打包静态页面
既然选择了远方,便只顾风雨兼程 __ HANS许 系列:零基础搭建前后端分离项目 系列:零基础搭建前后端分离项目 创建空项目 使用Less 使用TypeScript 使用WebPack 开始写项目 总 ...
- JAVA_新建一个方法并且求三个数中的最大值
package wac.wev.as;//新建一个方法在求最大值import java.util.Scanner; public class MaxLian {public static void m ...
- PHP制作个人博客-广告位添加与调用 推荐文章数据调取
上一节博客的导航我们已经动态调取,这一节我们主讲一下如何根据页面布局,后台添加广告位,及模板上动态调取广告.博客推荐文章的数据调用. 首先我们在云码博客的后台添加10条左右的测试数据,thinkcmf ...
- python迭代器与生成器及yield
一.迭代器(itertor) 1.可迭代: 在Python中如果一个对象有__iter__()方法或__getitem__()方法,则称这个对象是可迭代的(iterable). 其中__iter__( ...
- vue学习之ajax 简单快速使用axios
vue2.x 推荐使用axios 1.首先使用安装 npm install axios -S 2.在哪用在哪引入 import axios from 'axios' 或则在main.js 中引入 在申 ...
- wordpress 图片上传冲突
网上常见的wordpress图片上传 jQuery('#upload_image_button').click(function() { //formfield并未用上,可能代码遗漏了一段,怀疑和类的 ...
- SVN的使用说明
SVN管理版本是比较好的东西,但是我的SVN图标老是不出来,有时候莫名其妙就没有了,所以记录一下处理办法: 1.右键->TortoiseSVN->Settings->Icon Ove ...
- 【AO笔记】有关使用AO基于shp文件创建网络数据集的一个细节
前些日子,和群友交流时提及shp文件创建单一网络数据集的创建问题. 由于项目需求,用shp文件创建网络合适,所以不得不去找一些古老的代码资料... 以前的研究中,创建网络数据集是根据IDatasetC ...
- 小米平板6.0以上系统如何不用Root激活Xposed框架的步骤
在异常多公司的引流,或业务操作中,大多数需要使用安卓的神一般的Xposed框架,几天前我们公司买来了一批新的小米平板6.0以上系统,大多数都是基于7.0以上版本,大多数不能够获取Root超级权限,虽然 ...