A. Bear and Displayed Friends

Div2 的题,不写。


B. Bear and Forgotten Tree 3

这种东西怎么评蓝的?

Description

给定 \(n,d,h\),构造一棵有 \(n\) 个点,直径为 \(d\),高度为 \(h\) 的树。

\(n\le 10^5\)。

Solution

首先 \(d>2h\) 是无解的,\(d=h=1\) 且 \(n>2\) 的时候也无解。

对其它情况,先从根构造两条长度分别为 \(h\) 和 \(d-h\) 的链。

剩下的点如果 \(d=h\) 就随便挂在除根和叶子以外的位置上,\(d\neq h\) 就挂在根上。

Code
const int N=1e5+5;
int n,d,h;
int main()
{
n=read(),d=read(),h=read();
if(d>2*h) {printf("-1\n");return 0;}
if(d==1&&h==1&&n>2) {printf("-1\n");return 0;}
for(int i=2;i<=h+1;i++) cout<<i-1<<" "<<i<<endl;
for(int i=h+2;i<=d+1;i++) cout<<((i==h+2)?1:i-1)<<" "<<i<<endl;
for(int i=d+2;i<=n;i++) cout<<((d==h)?2:1)<<" "<<i<<endl;
return 0;
}

C. Bear and Polynomials

Description

定义一个多项式合法,当且仅当它满足:

  • 系数是整数
  • 任意项系数的绝对值小于等于 \(k\)
  • 最高次项系数不为 \(0\)

给你一个 \(n\) 次多项式 \(P(x)=\sum\limits_{i=0}^n a_i x^i\),保证其合法且 \(P(2)\neq 0\)。

现在你可以改变 \(P(x)\) 其中一项的系数,设新得到的多项式为 \(Q(x)\)。要求 \(Q(x)\) 合法,且 \(Q(2)=0\)。求可能得到多少种不同的 \(Q(x)\)。

Solution

发现我们只关心 \(P(2)\) 和 \(Q(2)\),不妨直接把 \(2\) 代入原式,\(P(2)=\sum\limits_{i=0}^n a_i 2^i\)。

这个形式长得像个二进制,那么我们就把每个 \(a_i\notin [0,1]\) 的系数向后进位,转换为一个二进制数。令 \(P(2)=\sum\limits_{i=0}^{n+1} b_i 2_i\),其中除 \(b_{n+1}\) 外的 \(b_i\) 均为 \(0\) 或 \(1\)。

那么只改一个系数 \(a_i\) 使之变合法,即当前的 \(P(2)\) 是 \(2^i\) 的倍数。这在二进制下等价于 \(<i\) 的 \(b_j\) 均为 \(0\)。

找到第一个 \(b_i\neq 0\) 的位置,从这里开始依次考虑答案,维护 \(P(2)\) 是它的几倍。如果倍数已经 \(>2k\) 就 break 掉即可。

Code
#define int long long
const int N=3e5+5;
int n,k,a[N],y[N];
signed main()
{
n=read(),k=read();
for(int i=0;i<=n;i++) a[i]=y[i]=read();
for(int i=0;i<=n;i++)
{
if(a[i]>0) a[i+1]+=a[i]/2,a[i]=a[i]%2;
else
{
if(a[i]%2) a[i+1]+=a[i]/2-1,a[i]=1;
else a[i+1]+=a[i]/2,a[i]=0;
}
}
int st=n;
for(int i=0;i<=n;i++) if(a[i]) {st=i;break;}
int now=0;
for(int i=n+1;i>st;i--)
{
now=(now<<1)+a[i];
if(abs(now)>2*k) break;
}
int ans=0;
for(int i=st;i>=0;i--)
{
if(abs(now)>2*k) break;
now=(now<<1)+a[i];
if(abs(y[i]-now)<=k&&(i!=n||y[i]!=now)) ans++;
}
printf("%lld\n",ans);
return 0;
}

D. Bear and Contribution

Description

有 \(n\) 个贡献值 \(v_1,v_2,\dots,v_n\),将其中一个贡献值 \(+5\) 需要花费 \(b\),将其中一个贡献值 \(+1\) 需要花费 \(c\)。

求需要使其中的 \(k\) 个贡献值相等的最小花费。

\(2\le n,k\le 2\times 10^5\),\(1\le b,c\le 2000\),\(|v_i|\le 10^9\)。

Solution

将 \(v_i\) 升序排序,从小到大枚举 \(k\) 个数相等后的值 \(x\)。

发现如果没有第一种操作,那么每个数增加到 \(x\) 的代价是单调的,令至少 \(k\) 个数变成 \(a_i\) 的最优方案一定是修改 \(a_{i-k+1}\) 到 \(a_i\) 这一段。

而第一种操作会对单调性造成影响。但是可以发现,对于所有 \(\bmod\ 5\) 的值相同的 \(v_i\),它们之间不会被 \(+5\) 的操作改变单调性。

同理,我们也可以得到 \(+5\) 操作对可能成为答案的数的影响:所有 \(v_i+j(j\in [0,4])\) 都可能成为最后的答案。

把 \(v_i\) 按 \(\bmod\ 5\) 的值分组,同时把询问也按此分组。那么同组的 \(v_i\) 之间单调;同组的询问之间也单调。

对每组分别维护属于答案的队列,每次新增元素时删除 \(5\) 组中代价最大的那个队首即可。

时间复杂度 \(O(n\log n)\),瓶颈在排序。

Code
#define int long long
const int N=2e5+5,inf=1e18;
int n,k,b,c,v[N];
vector<int> a[5],q[5];
int ans=inf,st[5],ed[5];
il int get(int x,int y) {return (y-x)/5*b+(y-x)%5*c;}
void solve(int id)
{
for(int i=0;i<5;i++) st[i]=0,ed[i]=-1;
int sum=0,now=0;
for(int I=0;I<q[id].size();I++)
{
int x=q[id][I],lst=I?q[id][I-1]:id;
now+=sum*((x-lst)/5)*b;
for(int i=0;i<5;i++)
{
while(ed[i]+1<a[i].size()&&a[i][ed[i]+1]<=x)
{
if(sum==k)
{
int mx=0;
for(int j=0;j<5;j++)
if(st[j]<=ed[j]) mx=max(mx,get(a[j][st[j]],x));
if(mx>get(a[i][ed[i]+1],x))
for(int j=0;j<5;j++)
if(st[j]<=ed[j]&&get(a[j][st[j]],x)==mx) {now-=mx,sum--,st[j]++;break;}
}
if(sum<k) sum++,ed[i]++,now+=get(a[i][ed[i]],x);
else break;
}
}
if(sum==k) ans=min(ans,now);
}
}
signed main()
{
n=read(),k=read(),b=read(),c=read();
b=min(b,5*c);
for(int i=1;i<=n;i++) v[i]=read();
sort(v+1,v+n+1);
int mn=abs(v[1]);
for(int i=1;i<=n;i++) v[i]+=mn;
for(int i=1;i<=n;i++)
{
a[v[i]%5].push_back(v[i]);
for(int j=0;j<5;j++) if(i==n||v[i]+j<v[i+1]) q[(v[i]+j)%5].push_back(v[i]+j);
}
for(int i=0;i<5;i++) solve(i);
printf("%lld\n",ans);
return 0;
}

E. Bear and Paradox

Description

见题面。

Solution

首先我们试图找到一个最优策略。这里用临项交换的 trick,设 \(i\) 排在 \(j\) 前面比反过来更优,有:

\[p_i\times (1-\frac{c(x+t_i)}{T})+p_j\times (1-\frac{c(x+t_i+t_j)}{T})>p_i\times (1-\frac{c(x+t_i+t_j)}{T})+p_j\times (1-\frac{c(x+t_j)}{T})
\]

化简得到 \(\dfrac{p_i}{t_i}> \dfrac{p_j}{t_j}\)。

也就是说我们将所有问题按照 \(\frac{p_i}{t_i}\) 降序排序,依次完成它们即可使得分最大。

对于给定的 \(c\),考虑如何判断是否合法。

所有 \(\frac{p_i}{t_i}\) 相同的点都可以任意互换顺序,我们可以处理出每个问题最早和最晚的完成时间,即每个问题最小和最大的得分。

题意要求所有最优策略均合法,从小到大枚举 \(p_i\),并维护所有 \(p_j<p_i\) 的 \(j\) 的最大得分。若其大于 \(i\) 的最小得分,则不合法。

容易发现这个东西具有单调性,可以二分 \(c\) 的值。

注意判断 \(\frac{p_i}{t_i}\) 的值相同时使用乘法判断 / 使用足够小的 \(\text{eps}\),否则会像樱雪喵一样炸精度从昨天晚上调到今天下午 /fn

Code
#define int long long
const double eps=1e-11;
const int N=1.5e5+5;
int n;
struct node
{
int p,t;
double d;
}a[N];
int sum[N],st[N],ed[N],b[N];
il bool cmp(node x,node y) {return x.d>y.d;}
il bool cmp2(int x,int y) {return a[x].p<a[y].p;}
il double get(int id,int t,double c)
{
return 1.0*a[id].p*(1-1.0*c*t/sum[n]);
}
double mx[N];
il bool check(double c)
{
int lst=0;
for(int i=1;i<=n;i++) mx[i]=get(b[i],st[b[i]],c);
for(int i=2;i<=n;i++) mx[i]=max(mx[i],mx[i-1]);
for(int i=1;i<=n;i++)
{
if(a[b[i]].p!=a[b[i-1]].p) lst=i-1;
if(get(b[i],ed[b[i]],c)<mx[lst]) return 0;
}
return 1;
}
signed main()
{
n=read();
for(int i=1;i<=n;i++) a[i].p=read(),b[i]=i;
for(int i=1;i<=n;i++) a[i].t=read(),a[i].d=1.0*a[i].p/a[i].t;
sort(a+1,a+n+1,cmp),sort(b+1,b+n+1,cmp2);
int lst=1;
for(int i=1;i<=n+1;i++)
{
sum[i]=sum[i-1]+a[i].t;
if(fabs(a[i].d-a[i-1].d)<eps) st[i]=st[i-1];
else
{
for(int j=lst;j<i;j++) ed[j]=sum[i-1];
lst=i,st[i]=sum[i-1];
}
}
for(int i=1;i<=n;i++) st[i]+=a[i].t;
double l=0,r=1;
while(r-l>1e-6)
{
double mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
printf("%.8lf\n",l);
return 0;
}

F. Bear and Chemistry

自己想出来的,感觉评 *3300 的主要原因是难写。

Descripiton

见题面。

Solution

题意的本质是判断点集 \(V\) 是否都属于同一个边双。

所以可以先将原图缩点成一棵树,每次询问时在树上加上新边重跑一遍边双判断答案。

但是这样是 \(O(nq)\) 的。

考虑优化时间复杂度,发现原图缩点后的树上很多点无效。只对与询问相关的点建出虚树,在虚树上跑边双不影响答案。

于是就做完了。

Code
#include<bits/stdc++.h>
#define il inline
using namespace std;
il long long read()
{
long long xr=0,F=1; char cr;
while(cr=getchar(),cr<'0'||cr>'9') if(cr=='-') F=-1;
while(cr>='0'&&cr<='9')
xr=(xr<<3)+(xr<<1)+(cr^48),cr=getchar();
return xr*F;
}
const int N=3e5+5;
int n,m,Q,U[N],V[N],R;
il int rotate(int x) {x=(x+R)%n;if(!x) x=n;return x;}
struct Tarjan
{
vector<int> V;
struct edge{int nxt,to;} e[N<<1];
int head[N],cnt=1;
il void add(int u,int v) {e[++cnt]={head[u],v};head[u]=cnt;}
int dfn[N],low[N],tot,bel[N],num;
stack<int> q;
void clear() {for(auto i:V) head[i]=0,dfn[i]=0;cnt=1,num=0;V.clear();}
void tarjan(int u,int lst)
{
dfn[u]=low[u]=++tot; q.push(u);
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to; if(i==(lst^1)) continue;
if(!dfn[v]) tarjan(v,i),low[u]=min(low[u],low[v]);
else low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
num++;
while("qwq")
{
int nw=q.top(); q.pop(),bel[nw]=num;
if(nw==u) break;
}
}
}
void solve() {for(auto i:V) if(!dfn[i]) tarjan(i,0);}
}st,tr;
vector<int> e[N];
struct LCA
{
int n,dfn[N],tot,st[21][N],fa[N],dep[N],rt[N];
il int get(int x,int y) {return dep[x]<dep[y]?x:y;}
void dfs(int u,int ff)
{
fa[u]=ff,dep[u]=dep[ff]+1,dfn[u]=++tot; st[0][dfn[u]]=ff;
for(auto v:e[u]) if(v^ff) dfs(v,u);
}
void init()
{
n=::st.num;
for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i,0),rt[i]=1;
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j<=n-(1<<i)+1;j++) st[i][j]=get(st[i-1][j],st[i-1][j+(1<<i-1)]);
}
int lca(int x,int y)
{
if(x==y) return x;
if((x=dfn[x])>(y=dfn[y])) swap(x,y);
int len=__lg(y-x);
return get(st[len][x+1],st[len][y-(1<<len)+1]);
}
}l;
struct node{int u,v;};
il bool cmp(int x,int y) {return l.dfn[x]<l.dfn[y];}
void build(vector<int> V,vector<node> E)
{
vector<int> a,b;
for(auto x:V) a.push_back(st.bel[x]);
for(auto x:E)
{
a.push_back(st.bel[x.u]),a.push_back(st.bel[x.v]);
}
sort(a.begin(),a.end(),cmp);
for(int i=1;i<a.size();i++) b.push_back(l.lca(a[i-1],a[i]));
for(auto x:a) b.push_back(x); b.push_back(1);
sort(b.begin(),b.end(),cmp),b.erase(unique(b.begin(),b.end()),b.end());
tr.V.clear(); for(auto x:b) tr.V.push_back(x);
for(int i=0;i+1<b.size();i++)
{
if(!b[i]||!b[i+1]||!l.lca(b[i],b[i+1])) continue;
tr.add(l.lca(b[i],b[i+1]),b[i+1]),tr.add(b[i+1],l.lca(b[i],b[i+1]));
}
for(auto x:E)
{
int u=st.bel[x.u],v=st.bel[x.v];
if(u!=v) tr.add(u,v),tr.add(v,u);
}
}
int main()
{
n=read(),m=read(),Q=read();
for(int i=1;i<=n;i++) st.V.push_back(i);
for(int i=1;i<=m;i++)
{
U[i]=read(),V[i]=read();
st.add(U[i],V[i]),st.add(V[i],U[i]);
}
st.solve();
for(int i=1;i<=m;i++)
{
int u=st.bel[U[i]],v=st.bel[V[i]];
if(u!=v) e[u].push_back(v),e[v].push_back(u);
}
l.init();
for(int i=1;i<=Q;i++)
{
int n=read(),m=read();
vector<int> V;vector<node> E;
for(int j=1;j<=n;j++) V.push_back(rotate(read()));
for(int j=1;j<=m;j++)
{
node nw;
nw.u=rotate(read()),nw.v=rotate(read());
E.push_back(nw);
}
build(V,E);
tr.solve();
for(int j=0;j<n;j++) V[j]=tr.bel[st.bel[V[j]]];
sort(V.begin(),V.end()),V.erase(unique(V.begin(),V.end()),V.end());
if(V.size()>1) printf("NO\n");
else R=(R+i)%(::n),printf("YES\n");
tr.clear();
}
return 0;
}

VK Cup 2016 - Round 1 (CF639)的更多相关文章

  1. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) B. Problems for Round 水题

    B. Problems for Round 题目连接: http://www.codeforces.com/contest/673/problem/B Description There are n ...

  2. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) B

    B. Problems for Round time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  3. VK Cup 2016 - Round 1 (Div. 2 Edition) C. Bear and Forgotten Tree 3

    C. Bear and Forgotten Tree 3 time limit per test 2 seconds memory limit per test 256 megabytes input ...

  4. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition)只有A题和B题

    连接在这里,->点击<- A. Bear and Game time limit per test 2 seconds memory limit per test 256 megabyte ...

  5. Codeforces Round #348(VK Cup 2016 - Round 2)

    A - Little Artem and Presents (div2) 1 2 1 2这样加就可以了 #include <bits/stdc++.h> typedef long long ...

  6. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition)

    A.暴力枚举,注意游戏最长为90分钟 B.暴力,c[l]++,c[r]--,记录中间有多长的段是大小为n的,注意特判m=0的情况 C.暴力枚举,我居然一开始没想出来!我一直以为每次都要统计最大的,就要 ...

  7. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D Bear and Two Paths

    题目链接: http://codeforces.com/contest/673/problem/D 题意: 给四个不同点a,b,c,d,求是否能构造出两条哈密顿通路,一条a到b,一条c到d. 题解: ...

  8. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) C - Bear and Colors

    题目链接: http://codeforces.com/contest/673/problem/C 题解: 枚举所有的区间,维护一下每种颜色出现的次数,记录一下出现最多且最小的就可以了. 暴力n*n. ...

  9. Codeforces Round #348 (VK Cup 2016 Round 2, Div. 2 Edition) D. Little Artem and Dance

    题目链接: http://codeforces.com/contest/669/problem/D 题意: 给你一个初始序列:1,2,3,...,n. 现在有两种操作: 1.循环左移,循环右移. 2. ...

  10. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D. Bear and Two Paths 构造

    D. Bear and Two Paths 题目连接: http://www.codeforces.com/contest/673/problem/D Description Bearland has ...

随机推荐

  1. 用写代码的方式画图-试下PlantUML吧

    1 序言 所谓一图胜千言,大家平日在工作中编写文档时,往往都需要画各种图来表达中心思想,比如流程图.时序图.UML 图,很多人选择使用 Axure .PrecessOn.Diagrams(darw.i ...

  2. 根据模板动态生成word(三)使用poi-tl生成word

    @ 目录 一.前言 1.什么是poi-tl 2.官方信息 2.1 源码仓库 2.2 中文文档 2.3 开源协议 3.poi-tl的优势 3.1 poi-tl和其他模板引擎的对比 3.2 poi-tl ...

  3. Hexo、Typecho博客添加旅行足迹网页

    本文部署的足迹地图,地址如下: http://www.aomanhao.top/index.php/archives/183/ jVectorMap JVectorMap 是一个优秀的.兼容性强的 j ...

  4. 快速搭建 phpmyadmin 开发环境

    真的很喜欢 phpmyadmin 这个 PHP 程序. 虽然工作上基本都用 Navicat,但是很多东西都是习惯了,就很难改变! 比如建表,执行 SQL 语句,界面操作肯定是 phpmyadmin 更 ...

  5. 信创啊,信创。Solon 的 war 包,现在同时支持 jakarta.servlet(及 javax.servlet)容器了!

    Solon 是个神奇的项目,不是基于 Servlet 的.但是又很支持 Servlet,尤其是 war 包.打起来还挺方便的. 如果你是做信创的(听说,很多信创项目是用 war 部署到 tomcat ...

  6. 利用文件包含漏洞包含ssh日志拿shell

    今天看文章学了一招,有包含漏洞无法传文件的时候用 目标服务器环境为ubuntu,ssh登录日志文件是/var/log/auth.log 找个Linux的环境执行ssh '<? phpinfo() ...

  7. [mysql]状态检查常用SQL

    前言 使用MySQL自身命令获取数据库服务状态. 连接数 -- 最大使用连接数 show status like 'Max_used_connections'; -- 系统配置的最大连接数 show ...

  8. 《深入理解Java虚拟机》读书笔记:Class类文件的结构

    Class类文件的结构 Sun公司以及其他虚拟机提供商发布了许多可以运行在各种不同平台上的虚拟机,这些虚拟机都可以载入和执行同一种平台无关的的程序存储格式--字节码(ByteCode),从而实现了程序 ...

  9. aspnetcore 注册中心 consul

    consul启动 . http://192.168.1.6:8500/ #以server方式启动,UI可以访问,boot引导自己选为leader,网段内PC可访问 consul agent -serv ...

  10. C++ ASIO 实现异步套接字管理

    Boost ASIO(Asynchronous I/O)是一个用于异步I/O操作的C++库,该框架提供了一种方便的方式来处理网络通信.多线程编程和异步操作.特别适用于网络应用程序的开发,从基本的网络通 ...