8.18爆炸记

T1

改造二叉树

Description

在计算机科学中,二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子”。二叉树常被用作二叉搜索树和二叉堆。
  我们再讨论二叉搜索树。什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设key[p]表示结点p上的数值,对于其中的每个结点p,若其存在左孩子lch,则key[p] > key[lch];若其存在右孩子rch,则key[p] < key[rch]。注意,应该是所有左子树中的key小于当前key,所有右子树中的key大于当前key。
  对于每个结点,无论如何改变其数值(整数),费用总等于1。
  现在给定一棵二叉树,可以任意修改结点的数值。要求用最小的费用将其变成一棵二叉搜索树。

Input

  输入文件bst.in包括两行,第一行是一个整数n,表示二叉树的结点数。
  第二行包含n个整数,用空格分隔,第i个整数ai是第i个结点的原始数值。
  此后n-1行每行两个整数,第i行描述编号为i-1的结点的父亲编号以及父子关系(0表示为左孩子,1表示为右孩子)。编号为1的结点一定是二叉树的根。

Output

 输出文件bst.out包括一行,这一行只包含一个整数,也就是最小的费用值。输入数据保证这个值小于2^31。

Sample Input

3 2 2 2 1 0 1 1

Sample Output

2

Hint

【数据范围】
  对于50%的数据,保证n<=100且0<=ai<=200;
  对于100%的数据,保证n<=100000;

二叉查找树的中序遍历具有一个优秀的性质,那就是严格递增。对于当前树,我们可以处理出它的中序遍历,问题就变为了:求最少在中序遍历中修改几个数,使它严格递增。

我们自然会想到求出它的最长上升子序列,并用n减去它的长度就是答案。但如何保证严格递增呢?常见的一个thick就是把每个数减去当前数的下标,但值得注意的是:此时求的就是最长不降子序列的长度了。

因为n≤105,故要用二分优化。

#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define INF 0x7fffffff
inline int read() {
    char ch;
    bool bj=0;
    while(!isdigit(ch=getchar()))
        bj|=(ch==‘-‘);
    int res=ch^(3<<4);
    while(isdigit(ch=getchar()))
        res=(res<<1)+(res<<3)+(ch^(3<<4));
    return bj?-res:res;
}
void printnum(int x) {
    if(x>9)printnum(x/10);
    putchar(x%10+‘0‘);
}
inline void print(int x,char ch) {
    if(x<0) {
        putchar(‘-‘);
        x=-x;
    }
    printnum(x);
    putchar(ch);
}
int n,a[200005],c[200005][2];
int d[200005],Mid[200005],tot;
void DFS(int x) {
    if(c[x][0])DFS(c[x][0]);
    Mid[++tot]=a[x];
    if(c[x][1])DFS(c[x][1]);
}
int Half_LIS() {
    int len=1;
    d[1]=Mid[1];
    for(int i=2; i<=n; i++) {
        int l=1,r=len;
        if(d[len]<=Mid[i]) {
            len++;
            d[len]=Mid[i];
            continue;
        }
        while(l<=r) {
            int    mid=(l+r)>>1;
            if(d[mid]<=Mid[i])l=mid+1;
            else r=mid-1;
        }
        d[l]=Mid[i];
    }
    return len;
}
signed main() {
    n=read();
    for(int i=1; i<=n; i++)a[i]=read();
    int x,y;
    for(int i=2; i<=n; i++) {
        x=read();
        y=read();
        c[x][y]=i;
    }
    DFS(1);
    for(int i=1; i<=n; i++)Mid[i]-=i;
    cout<<n-Half_LIS()<<endl;
    return 0;
}

T2

数字对

Description

 小H是个善于思考的学生,现在她又在思考一个有关序列的问题。
  她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n)。
  这个特殊区间满足,存在一个k(L <= k <= R),并且对于任意的i(L <= i <= R),ai都能被ak整除。这样的一个特殊区间 [L, R]价值为R - L。
  小H想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?这些区间又分别是哪些呢?你能帮助她吧。

Input

  第一行,一个整数n.
  第二行,n个整数,代表ai.

Output

  第一行两个整数,num和val,表示价值最大的特殊区间的个数以及最大价值。
  第二行num个整数,按升序输出每个价值最大的特殊区间的L.

Sample Input

【样例输入1】
5
4 6 9 3 6

【样例输出1】
1 3
2

Sample Output

【样例输入2】
5
2 3 5 7 11

【样例输出2】
5 0
1 2 3 4 5

Hint

【数据范围】
  30%: 1 <= n <= 30 , 1 <= ai <= 32.
  60%: 1 <= n <= 3000 , 1 <= ai <= 1024.
  80%: 1 <= n <= 300000 , 1 <= ai <= 1048576.
  100%: 1 <= n <= 500000 , 1 <= ai < 2 ^ 31.

30pts:暴力,枚举每个区间,暴力扫。

60pts:ST表预处理区间最小和区间gcd,显然成为特殊区间的条件就是区间最小和区间gcd相等,枚举每个区间,O(1)算(笔者没算gcd的复杂度)

100pts:是否可以二分?如果我们二分点i向右延伸的长度的话,这个答案是不具有单调性的。但是如果二分最大价值就可以,设当前二分的答案是mid,O(n)暴力判一遍[i,i+mid]所有区间是否为特殊区间,求答案的最大值即可

不用ST表用线段树的话会T飞,同桌亲测与暴力分一样。推荐遇到静态问题或多次查询的题都用ST表。

#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define int long long
inline int read() {
    char ch;
    bool bj=0;
    while(!isdigit(ch=getchar()))
        bj|=(ch==‘-‘);
    int res=ch^(3<<4);
    while(isdigit(ch=getchar()))
        res=(res<<1)+(res<<3)+(ch^(3<<4));
    return bj?-res:res;
}
void printnum(int x) {
    if(x>9)printnum(x/10);
    putchar(x%10+‘0‘);
}
inline void print(int x,char ch) {
    if(x<0) {
        putchar(‘-‘);
        x=-x;
    }
    printnum(x);
    putchar(ch);
}
int p[500005][25],a[500005],n,log_2[500005],minn[500005][25];
int maxn=-INF;
int tot,ans[500005];
int gcd(int x,int y) {
    return y?gcd(y,x%y):x;
}
inline void ST() {
    for(int j=1; j<=log_2[n]; j++)
        for(int i=1; i<=n; i++)
            if(i+(1<<j)-1<=n) {
                p[i][j]=gcd(p[i][j-1],p[i+(1<<(j-1))][j-1]);
                minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
            }
}
inline int check(int x,int y) {
    int k=log_2[y-x+1];
    return gcd(p[x][k],p[y-(1<<k)+1][k])==min(minn[x][k],minn[y-(1<<k)+1][k]);
}
inline void Solve(int x) {
    for(int i=1; i<=n; i++)
        if(i+x<=n&&check(i,i+x))
            ans[++tot]=i;
}
signed main() {
    n=read();
    for(int i=2; i<=n; i++)log_2[i]=log_2[i>>1]+1;
    for(int i=1; i<=n; i++) {
        a[i]=read();
        p[i][0]=minn[i][0]=a[i];
    }
    ST();
    int l=0,r=n;
    while(l<=r) {
        int mid=(l+r)>>1;
        tot=0;
        Solve(mid);
        if(tot) {
            maxn=mid;
            ans[0]=tot;
            l=mid+1;
        } else r=mid-1;
    }
    print(ans[0],‘ ‘);
    print(maxn,‘\n‘);
    for(int i=1; i<=ans[0]; i++)print(ans[i],‘ ‘);
    return 0;
}

T3

交换

Description

给定一个{0, 1, 2, 3, … , n - 1}的排列 p。一个{0, 1, 2 , … , n - 2}的排列q被认为是优美的排列,当且仅当q满足下列条件:
对排列s = {0, 1, 2, 3, ..., n - 1}进行n – 1次交换。
1.交换s[q0],s[q0 + 1]
2.交换s[q1],s[q1 + 1]
…
最后能使得排列s = p.
问有多少个优美的排列,答案对10^9+7取模。

Input

第一行一个正整数n.
第二行n个整数代表排列p.

Output

仅一行表示答案。

Sample Input

3
1 2 0

Sample Output

【样例输出】
1

Hint

【样例解释】
q = {0,1} {0,1,2} ->{1,0,2} -> {1, 2, 0}
q = {1,0} {0,1,2} ->{0,2,1} -> {2, 0, 1}
【数据范围】
30%: n <= 10
100%: n <= 50

原文地址:https://www.cnblogs.com/soledadstar/p/11373766.html

时间: 2024-07-31 15:51:22

8.18爆炸记的相关文章

GDOI2018爆炸记

Day0 12:45p.m. 从初中部出发前回班探望了一下同学,受到热烈欢迎(?) 13:15p.m. 出发去中山,路上本来想用mac看fz的,结果ass字幕导入失败,心态爆炸*1:后来成功获取xfz手机热点,结果十五分钟后网络GG,心态爆炸*2:感觉这就是旅游选手面对死亡的前兆,于是开始睡觉. 15:00p.m. 到达中山,感觉好快啊……还不到2h,觉都没睡好.在高中部集训了一个月,从来都没有见过闹市区,有一种山区贫困儿童进城的即视感,看到高大上(?)的酒店纷纷表示赞叹与惊奇.(对今年送的黄色

20190614考试心态爆炸记

昨天波波说今天有可能考ac自动机(被奶死),我就莫名慌得一批(好吧其实他说考什么我都会慌得一批),当时我看ac自动机还懵逼呢,然后预示今天考试凉凉? 上午淼哥又说下午以来就考试,于是更加慌得一批. 今天早上开刷ac自动机,抄了skyh的板子A掉了T1裸板子,然后第二题水题就不会然后预示今天考试凉凉?调了一个上午,结果发现两个‘=’打成一个‘=’ 然后又去loj上交了一遍一打开首页发现,心态爆炸,完了,我肯定爆零了,完了,我要去菜机房了,凉凉. 中午走前颓下了所有板子然而并没有什么卵用 下午刚起床

小蒟蒻初次CF滚粗+爆炸记 (Codeforces Round #466 Div.2)

比赛链接:http://codeforces.com/blog/entry/57981 小蒟蒻今天初次在ZCDHJ张大佬的带领下,打了一场CF (张大佬cnblogs链接:https://www.cnblogs.com/ZCDHJ)' 英文完全看不懂,后面几题直接放弃,各位dalao请见谅 T1: 题目链接:http://codeforces.com/contest/940/problem/A 题目大意: 给你一个n个数的集合,要求你删掉若干数,其中最大的差不应该超过d,求最小删除量. (小蒟蒻

SDOI2018Round1 &amp;&amp; 九省联考 爆炸记

Day 0 做了一上午火车,大概中午十二点左右到了烟台核电培训中心宾馆,宾馆蛮不错的,跟我在北京参加英才论坛时住的宾馆舒适程度上差不多. 下午花式颓颓颓,吃了晚饭(体验一般)去试机,听说用Lemon评测,开栈,开O2,lld与I64d均可. 晚上回去颓颓颓. Day 1 早上发现SA忘没了赶紧写了写.早饭体验一般. 开考啦. 读题: T1:嗯..看上去很可做的表征博弈论内核应该是个DP的题目,暴力能拿55,先放一放. T2:嗯..贪心傻逼题?50%数据\(d_i\)互不相同?有坑? T3:嗯..

屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

游戏中可能经常会遇到需要某个物体跟着鼠标移动,然后又需要把物体放在某个鼠标指定的位置 实现方式 Camera.main.WorldToScreenPoint Camera.main.ScreenToWorldPoint 3D打地鼠实例 我这里用到的素材都比较简陋,几乎全是用Unity做的 首先是锤子 就是两个Cylinder,在把手的位置放一个空物体用于模拟锤子的动作,命名为Hammer,把锤子作为Hammer的子物体,给Hammer添加Animation动画: 在三个关键帧位置设置Hammer

[JAVA][2013蓝桥杯预赛 JAVA本科B组][振兴中华]

标题: 振兴中华 小明参加了学校的趣味运动会,其中的一个项目是:跳格子. 地上画着一些格子,每个格子里写一个字,如下所示:(也可参见p1.jpg) 从我做起振 我做起振兴 做起振兴中 起振兴中华 比赛时,先站在左上角的写着"从"字的格子里,可以横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置.一直要跳到"华"字结束. 要求跳过的路线刚好构成"从我做起振兴中华"这句话. 请你帮助小明算一算他一共有多少种可能的跳跃路线呢? 答案是一个整数,

蓝的成长记——追逐DBA(18):小机上WAS集群故障,由一次更换IP引起

原创作品.出自 "深蓝的blog" 博客,欢迎转载,转载时请务必注明出处.否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlong/article/details/47720043 [简单介绍] 个人在oracle路上的成长记录,当中以蓝自喻.分享成长中的情感.眼界与技术的变化与成长.敏感信息均以其他形式去掉,不会泄露不论什么企业机密,纯为技术分享. 创作灵感源于对自己的自省和记录.若能对刚刚起步的库友起到些许的帮助或共鸣,欣慰不已.

SQL Server 字段类型 decimal(18,6)小数点前是几位?记一次数据库SP的BUG处理

原文:SQL Server 字段类型 decimal(18,6)小数点前是几位?记一次数据库SP的BUG处理 SQL Server 字段类型 decimal(18,6)小数点前是几位? 不可否认,这是一个很低级的问题.... 为什么会问这么低级的问题? 由于这个问题,导致一个数据导入的SP执行失败....以至于困扰了我好几个小时.... 事情是这样的... 公司总部上了一套Oracle的ERP,我们系统中有些数据要从里面取,比如Supplier,Product等. Oracle会导出数据文件,我

记一次centos6.6升级linux内核至3.18.24

linux kernel的官网上可以自行选择各版本的内核下载 官网: https://www.kernel.org/ 下载长期支持版3.18.24 wget https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.18.24.tar.xz 解压 tar -xvf linux-3.18.24.tar.xz mv linux-3.18.24 /usr/src/ cd /usr/src ln -s linux-3.18.24 linux cd linu