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. 【原创】xenomai UDD介绍与UDD用户态驱动示例

    目录 xenomai UDD与用户态驱动示例 一.UDD介绍 二.UDD原理及框架 1. 内存映射 2. 中断处理 UDD与UIO的区别 3. linux UIO与xenomai UDD框架对比 3. ...

  2. 2023年郑州轻工业大学校赛邀请赛myh

    赛程回顾和赛后总结 赛程回顾 although 昨天刚复盘的,但还是记不住题号.就口胡下是那类型题吧. 刚开始时,我和队长先看的a,让jc去找签到题.我们看了下a,队长说可能dp,但还是感觉没啥思路就 ...

  3. Centos7中Oracle占用CPU过高(解决方案)

    Centos7中Oracle占用CPU过高(解决方案) 前言: 99%的问题几乎都是SQL的问题,一般SQL可能会出现以下几种情况: 相关SQL搜索条件没有加索引 索引失效 联合查询过多 数据量过大 ...

  4. MyBatis使用注解开发(及Sqlsession连接器的本质)

    使用注解开发 底层实现机制是反射和,动态代码.反射可以获得这个类的方法属性还可以创建对象,执行方法. 面向接口编程 之前学过,面向对象编程,也学习过接口.但是真正的开发中,很多时候我们会选择面向接口编 ...

  5. .NET周刊【7月第4期 2023-07-23】

    国内文章 你知道.NET的字符串在内存中是如何存储的吗? https://www.cnblogs.com/artech/p/string-memory-layout.html 毫无疑问,字符串是我们使 ...

  6. 实践分析丨AscendCL应用编译&运行案例

    本文分享自华为云社区<AscendCL应用编译&运行问题案例>,作者: 昇腾CANN. AscendCL(Ascend Computing Language)是一套用于在昇腾平台上 ...

  7. 2023牛客暑期多校训练营4 AFHJL

    比赛链接 A 题解 知识点:KMP,构造. 考虑构造全 \(0,1\) 串,至少有一个可行. 我们只需要考虑到 \(t\) 的border \(t'\) ,即 \(t'+s+t'\) : 当 \(t' ...

  8. 园子的商业化努力-阿里云开发者社区合作:RDS MySQL Serverless 免费试用活动

    阿里云开发者社区这个月组织了一个针对"云数据库 RDS MySQL Serverless 版"免费试用用户的做任务活动,上周找园子合作,希望能在园子里推广一下这个活动. 由于时间太 ...

  9. Jenkins远程执行shell脚本,超时报错(ERROR: Exception when publishing, exception message [Exec timed out or was interrupted after 120,001 ms])

    通过Jenkins远程执行脚本时,发现Jenkins构建任务失败,但是服务器本身的脚本是生效的. 排查确认是Jenkins构建任务超时,导致Jenkins看板显示任务构建失败,但是服务器上的自动脚本执 ...

  10. AVR汇编(七):位操作和MCU控制指令

    AVR汇编(七):位操作和MCU控制指令 位操作指令 SBI / CBI SBI 指令用于设置I/O寄存器中的第 b 位, CBI 指令用于清除I/O寄存器中的第 b 位. 例如: SBI DDRB, ...