[比赛题解]CWOI2019-1

比赛日期:2019.10.12

T1

一道神仙DP题。

我们考虑\(dp[i][j][k]\)表示最后\(i\)位数,\(i-1\)位都是9,最后一位为\(j\),最后\(i\)位数以前的部分最大数为\(k\)时,把最后\(i\)位数减到负数最小需要多少次。\(re[i][j][k]\)代表这个状态下,把这个数减到负数时,负数+10的值。

那么每次操作就会减去\(min(最后i位数中最小值,k)\)。

我们先预处理出\(dp\)和\(re\)数组(从低位向高位递推)。

然后读入给的数,考虑把除1之外所有位数变成9。那么从第二位向高位枚举,每次把当前位减掉1,直到减到9(最后一次注意退位),同时记录在这个过程中走了多少步。因为对于一个前缀全为9,最后一位无论是什么,减去一个小于10的数得到的数的前缀还是全为9。

全部变成9之后即可从高位到低位统计答案即可。

貌似状态设置成“全是9”也可以,但是没试过。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
long long dp[20][10][10],res[20][10][10];
long long ans=0;
char s[20];
int num[20];
void init() {
for(int i=0;i<=9;i++) {
for(int j=0;j<=9;j++) {
if(i<j) {//当前位较小
dp[1][i][j]=1;
res[1][i][j]=i-j+10;
}
else {//当前位较大
dp[1][i][j]=2;
res[1][i][j]=10-j;
}
}
}
for(int i=2;i<=18;i++) {
for(int j=0;j<=9;j++) {
for(int k=0;k<=9;k++) {
res[i][j][k]=j;
for(int n=9;n>=0;n--) {
dp[i][j][k]+=dp[i-1][res[i][j][k]][max(n,k)];
res[i][j][k]=res[i-1][res[i][j][k]][max(n,k)];
}
}
}
} }
void just_do_it() {
scanf("%s",s+1);int len=strlen(s+1);
for(int i=1;i<=len;i++)num[i]=s[i]-'0';
reverse(num+1,num+1+len);
int now=num[1];
for(int i=2;i<=len;i++) {
while(num[i]!=9) {
int ma=0;
for(int j=i;j<=len;j++)ma=max(ma,num[j]);
if(!ma)break;//无法退位
num[i]--;
for(int j=i;num[j]<0;j++) {//退位
num[j]=9;num[j+1]--;
}
ans+=dp[i-1][now][ma];
now=res[i-1][now][ma];
}
}
for(int i=len;i>=2;i--) {
while(num[i]) {
ans+=dp[i-1][now][num[i]];
now=res[i-1][now][num[i]];
num[i]--;
}
}
if(now)ans++;
printf("%lld",ans);
}
int main() {
init();
just_do_it();
}

T2

我们考虑三种情况

  1. 被覆盖点为祖先-后代关系
  2. 被覆盖点没有祖先-后代关系
  3. 被覆盖点相等

这三类都可以转换为统计某些点的子树内点的个数。(比如说第二种情况就是统计路径两端分别在\(u,v\)子树内的路径条数)。对于一个端点,我们可以把他转换为\(dfs\)序在一定范围内的点,而对于一条路径,我们可以把它转换成矩阵坐标在一定范围内的点。然后扫描线二维数点就好了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#define int long long
#define ll long long
using namespace std;
const int maxn=1e5+1000;
int root[maxn],ls[maxn*80],rs[maxn*80],head[maxn],cnt,idx,n,m,dep[maxn],po[maxn],f[maxn][23],size[maxn],dfn[maxn],dfn_cnt;
ll ans1=0,ans2,ans3,sum[maxn*80];
vector<int>list[maxn];
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
struct gg {
int u,v,next;
}side[maxn*2];
//pair<int,int>ori[maxn];
struct data {
int first,second;
}ori[maxn];
void insert(int u,int v){
struct gg add={u,v,head[u]};side[++cnt]=add;head[u]=cnt;
}
void dfs(int now,int fa) {
dep[now]=dep[fa]+1;size[now]=1;dfn[now]=++dfn_cnt;
f[now][0]=fa;for(int i=1;i<=22;i++)f[now][i]=f[f[now][i-1]][i-1];
for(int i=head[now];i;i=side[i].next) {
int v=side[i].v;if(v==fa)continue;
dfs(v,now);size[now]+=size[v];
}
}
int lca(int u,int v) {
if(dep[u]<dep[v])swap(u,v);
for(int i=22;i>=0;i--)if(dep[f[u][i]]>=dep[v])u=f[u][i];
if(u==v)return u;
for(int i=22;i>=0;i--)if(f[u][i]!=f[v][i]){u=f[u][i],v=f[v][i];}
return f[u][0];
}
int build(int l,int r) {//主席数,版本表示u的范围,线段树表示v的范围
int now=++idx;
if(l==r)return now;
int mid=(l+r)>>1;
ls[now]=build(l,mid);
rs[now]=build(mid+1,r);
return now;
}
bool cop(data x,data y) {
return x.first<y.first;
}
int insert(int sync,int l,int r,int tar) {
int now=++idx;
ls[now]=ls[sync],rs[now]=rs[sync],sum[now]=sum[sync]+1;
if(l==r)return now;
int mid=(l+r)>>1;
if(tar<=mid) {
ls[now]=insert(ls[sync],l,mid,tar);
}
else {
rs[now]=insert(rs[sync],mid+1,r,tar);
}
return now;
}
ll query(int sy1,int sy2,int l,int r,int tl,int tr) {
ll tot=sum[sy2]-sum[sy1];
if(tl<=l&&r<=tr)return tot;
tot=0;int mid=(l+r)>>1;
if(tl<=mid) {
tot+=query(ls[sy1],ls[sy2],l,mid,tl,tr);
}
if(tr>=mid+1) {
tot+=query(rs[sy1],rs[sy2],mid+1,r,tl,tr);
}
return tot;
}
int jump(int l,int h) {
for(int i=22;i>=0;i--)if(dep[f[l][i]]>dep[h])l=f[l][i];
return l;
}
signed main() {
scanf("%lld%lld",&n,&m);
for(int i=1;i<n;i++){int u,v;scanf("%lld%lld",&u,&v);insert(u,v);insert(v,u);}
dfs(1,0);
for(int i=1;i<=m;i++) {
scanf("%lld%lld",&ori[i].first,&ori[i].second);
if(dep[ori[i].first]>dep[ori[i].second])swap(ori[i].first,ori[i].second);
if(ori[i].first==ori[i].second)po[ori[i].first]++;
list[dfn[ori[i].first]].push_back(dfn[ori[i].second]);
list[dfn[ori[i].second]].push_back(dfn[ori[i].first]);
}
root[0]=build(1,m);sort(ori+1,ori+1+m,cop);
for(int i=1;i<=n;i++) {
root[i]=root[i-1];
for(int j=0;j<list[i].size();j++)root[i]=insert(root[i],1,n,list[i][j]);
} //for(int i=1;i<=n;i++)
for(int i=1;i<=m;i++) {
int u=ori[i].first,v=ori[i].second;//查询u,v被多少路径包含 //int lu,lv,ru,rv;
if(lca(u,v)==u) {//祖先-儿子关系
int p=jump(v,u);
ans1+=query(root[0],root[dfn[p]-1],1,n,dfn[v],dfn[v]+size[v]-1);
ans1+=query(root[dfn[p]+size[p]-1],root[n],1,n,dfn[v],dfn[v]+size[v]-1);
}
else {
ans1+=query(root[dfn[u]-1],root[dfn[u]+size[u]-1],1,n,dfn[v],dfn[v]+size[v]-1);
// ans1+=query(root[dfn[v]-1],root[dfn[v]+size[v]-1],1,n,dfn[u],dfn[u]+size[u]-1);
}
ans1--;
}
ans2=m*(m-1)/2;ans3=gcd(ans1,ans2);
cout<<ans1/ans3<<'/'<<ans2/ans3;
return 0;
}

[比赛题解]CWOI2019-1的更多相关文章

  1. 纪中OJ 2019.02.15【NOIP提高组】模拟 B 组 梦回三国 比赛题解(第一个)

    声明 旁边的同学小 H(胡)对我说: “哟,比赛拿了 140,强!要知道,如果哥第三题 AC 了,哥就 230 了,你个废柴!!!(比赛实际分数 130 额呵)” 顿时,千万草泥马从我心中奔腾而过:你 ...

  2. 洛谷P2460 [SDOI2007]科比的比赛(题解)(贪心+搜索)

    科比的比赛(题解)(贪心+搜索) 标签:算法--贪心 阅读体验:https://zybuluo.com/Junlier/note/1301158 贪心+搜索 洛谷题目:P2460 [SDOI2007] ...

  3. 【codeforces】【比赛题解】#960 CF Round #474 (Div. 1 + Div. 2, combined)

    终于打了一场CF,不知道为什么我会去打00:05的CF比赛…… 不管怎么样,这次打的很好!拿到了Div. 2选手中的第一名,成功上紫! 以后还要再接再厉! [A]Check the string 题意 ...

  4. 【codeforces】【比赛题解】#950 CF Round #469 (Div. 2)

    剧毒比赛,至少涨了分对吧.: ( [A]Left-handers, Right-handers and Ambidexters 题意: 有\(l\)个右撇子,\(r\)个左撇子,\(a\)个双手都惯用 ...

  5. 【codeforces】【比赛题解】#931 CF Round #468 (Div. 2)

    因为太迟了,所以没去打. 后面打了Virtual Contest,没想到拿了个rank 3,如果E题更快还能再高,也是没什么想法. [A]Friends Meeting 题意: 在数轴上有两个整点\( ...

  6. 【codeforces】【比赛题解】#937 CF Round #467 (Div. 2)

    没有参加,但是之后几天打了哦,第三场AK的CF比赛. CF大扫荡计划正在稳步进行. [A]Olympiad 题意: 给\(n\)个人颁奖,要满足: 至少有一个人拿奖. 如果得分为\(x\)的有奖,那么 ...

  7. 【codeforces】【比赛题解】#862 CF Round #435 (Div.2)

    这次比赛打得很舒服,莫名得了个Rank41,涨了219的Rating,就比较优秀.不过还是没有闫神厉害啊.题目链接::P. [A]MEX 题意: Evil博士把Mahmoud和Ehab绑架到了邪恶之地 ...

  8. 【codeforces】【比赛题解】#855 Codefest 17

    神秘比赛,以<哈利波特>为主题……有点难. C题我熬夜切终于是写出来了,可惜比赛结束了,气啊. 比赛链接:点我. [A]汤姆·里德尔的日记 题意: 哈利波特正在摧毁神秘人的分灵体(魂器). ...

  9. 【codeforces】【比赛题解】#869 CF Round #439 (Div.2)

    良心赛,虽然我迟了半小时233333. 比赛链接:#869. 呃,CF的比赛都是有背景的……上次是<哈利波特>,这次是<物语>…… [A]巧妙的替换 题意: Karen发现了石 ...

随机推荐

  1. 5分钟上手:本地开发环境启动HTTPS

    今天我们访问的所有网站几乎都是受HTTPS保护的.如果你的站点还没有,那你应该使用它.使用HTTPS保护服务器也意味着你不能从不是HTTPS服务器向此服务器发送请求.这给使用本地开发环境的开发人员带来 ...

  2. 2019-11-26-C#-判断方法是否被子类重写

    原文:2019-11-26-C#-判断方法是否被子类重写 title author date CreateTime categories C# 判断方法是否被子类重写 lindexi 2019-11- ...

  3. WPF toolkit AutoCompleteBox

    checked http://www.broculos.net/2014/04/wpf-autocompletebox-autocomplete-text.html#.WGNnq4N95aQ. 1.S ...

  4. POC挖矿没有前途

    最好的工作量证明是能力证明,能力不适合存储.望文生义,能力的本质意义是“能”和“力”(所有的词汇都按照望文生义理解,因为所有不能望文生义的词汇都是不良的已经被前人修正或将来被后人修正)能力是流动的,迁 ...

  5. .net webapi跨域问题

    2019年11月8日,近期做项目开始实行前后端分离的方式开发,前端使用vue的框架,打包发布后,调用后端接口出现跨域的问题,网上搜索出来的都是以下的配置方式: 但是,在我的项目中,按这种方式配置没有效 ...

  6. Asp.Net或WebAPI获取表单数据流(批量文件上传)

    //Web或WebAPI获取表单数据流(批量文件上传)        public JsonResult UploadFile()        {            //HttpPostedFi ...

  7. XMind破解版,2019年8月好使

    越来越多的公司用思维导图了,进行编写测试用例,以下为破解版,亲身实验才发 的  ,中国时间2019年8月5日 下载安装包: 链接:https://pan.baidu.com/s/1-ubJLPSEpH ...

  8. JVM 学习总结

    目录 Java内存区域 运行时数据区 & Java 内存结构 & Java 内存区域 1. 程序计数器 2. Java 虚拟机栈 3. 本地方法栈 4. 堆 5. 方法区 6. 运行时 ...

  9. Java自学-集合框架 ArrayList常用方法

    ArrayList常用方法 步骤 1 : 增加 add 有两种用法: 第一种是直接add对象,把对象加在最后面 heros.add(new Hero("hero " + i)); ...

  10. 二十:职责链模式详解(类似于spring的hangler处理请求)

    定义:为了避免请求的发送者和接收者之间的耦合关系,使多个接受对象都有机会处理请求.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. “看这个定义,就是将一堆可以处理请求的对象连 ...