洛谷2018寒假集训tg第二次比赛第二题Princess Principal题解

这算不算泄题啊。。。被kkk发现会咕咕咕吧。

题目大意:给定一个数列a,与常数n,m,k然后有m个询问,每个询问给定l,r。问在a[l]到a[r]中最少分成几段,使每段的和不超过k,如果无解,输出Chtholly

样例:

input:

5 5 7
2 3 2 3 4
3 3
4 4
5 5
1 5
2 4

output:

1
1
1
2
2

解答:

首先观察数据范围,n<=1e+6 可能的复杂度为O(mlogn).暴力能搞30分吧。

其实这题还是很妙的。我们先考虑暴力:对于[L,R],设个res,对[l,r]从左往右扫描,将res累加,当res大于k,ans++;当扫描到一个数大于k输出无解

我们可以发现这题是基于贪心的思想,使一个连续子段和尽量大。然后就有点难想了。

您觉得,这道题与树有关系吗?

还真有关系!!记得树的父亲表示法吗?对于n个节点,只要一个序列an即可表示这棵树。

先不考虑无解

对于a[x]我们设ax加到a(y-1)<=k 且ax加到a(y)>k 那么,我们将y当作x的父亲这样就可以弄一颗树

举个栗子:

样例:2 3 2 3 4

k=7 a4是a1的父亲

a4是a2的父亲

a5是a2的父亲

同时设一个root

root是a4的父亲

root是a5的父亲

我们发现,一个点从一个节点转移的另一个节点,等价于在原数列上直接跳过它的最有连续子段。

树上父亲节点的元素编号总是大于儿子

问题转化成:给定树上两点

求较低的点向上走到点p使p的元素编号大于顶一个点需要走几条边。

纯模拟跟暴力复杂度一样O(mn)

其实可以用倍增优化,有点类似于倍增求lca我们设anc[u][i]为u上方2^i个节点

有anc[u][i]=anc[anc[u][i-1]][i-1]

然后再加一个dis数组来存每个点的深度,答案就是一个点跳完后与跳之前的dis之差——差分思想

然后我们再来看如何判无解:

无解是由一种情况有a[i]>k(l<=i<=r)产生的

我们再建树时如果发现a[p]大于k那么就舍弃这个点

最后的树不止有一颗,是个森林。

第一次写博客,不懂可在下方提问。。。。

code:

// luogu-judger-enable-o2
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 1000010
struct edge{int to,nxt;}e[maxn<<1];
bool jg[maxn];
int fa[maxn],gf[maxn],n,m,k,a[maxn],dis[maxn],anc[maxn][21],head[maxn],pos;
void add(int u,int v){e[++pos]=(edge){v,head[u]},head[u]=pos;e[++pos]=(edge){u,head[v]},head[v]=pos;}
int ab(int x){return x>0 ? x:-x;}
void dfs(int u,int ft){
    int i;
    for(i=head[u];i;i=e[i].nxt){
        int v=e[i].to;if(v==ft)continue;
        dis[v]=dis[u]+1;
        gf[v]=gf[u];
        fa[v]=u;
        anc[v][0]=u;dfs(v,u);
    }
}
void init(){
    int j,i;
    for(i=1;i<=n;++i)anc[i][1]=anc[anc[i][0]][0];
    for(j=2;j<=20;++j)
        for(i=1;i<=n;++i)anc[i][j]=anc[anc[i][j-1]][j-1];
}
int slove(int x,int y){
    int ans=1,i;if(x>y)swap(x,y);
    for(i=20;i>=0;--i)
    if(anc[x][i]<=y && anc[x][i])
    ans+=dis[x]-dis[anc[x][i]],x=anc[x][i];
    return ans;
}
int main(){//freopen("in.txt","r",stdin);freopen("o1.txt","w",stdout);
    scanf("%d%d%d",&n,&m,&k);int i,j;
    for(i=1;i<=n;++i)scanf("%d",&a[i]);a[n+1]=1<<30;
    for(i=1;i<n;++i){
        long long res=0;if(a[i]>k){
            jg[i]=1;continue;
        }
        for(j=i;j<=n+1;++j){
            if(a[j]>k){
                --j;break;
            }
            res+=a[j];if(res>k){
                --j;break;
            }
        }
        add(i,j+1);
    }add(n,n+1);
    for(i=n+1;i>0;--i)
        if(!gf[i]){
            gf[i]=i;dfs(i,-1);
        }
        init();
    while(m--){
        int x,y;scanf("%d%d",&x,&y);
        if(gf[x]!=gf[y] || jg[x] || jg[y])printf("Chtholly\n");
        else {
            printf("%d\n",slove(x,y));
        }
    }
}
/*
5 1 10
2 5 5 2 5
1 5
*/

原文地址:https://www.cnblogs.com/david--lj/p/8467936.html

时间: 2024-10-01 20:49:34

洛谷2018寒假集训tg第二次比赛第二题Princess Principal题解的相关文章

洛谷 P2717 寒假作业

题目背景 zzs和zzy正在被寒假作业折磨,然而他们有答案可以抄啊. 题目描述 他们共有n项寒假作业.zzy给每项寒假作业都定义了一个疲劳值Ai,表示抄这个作业所要花的精力.zzs现在想要知道,有多少组连续的寒假作业的疲劳值的平均值不小于k? 简单地说,给定n个正整数A1,A2,A3,...,An,求出有多少个连续的子序列的平均值不小于k. 输入输出格式 输入格式: 第一行两个正整数,n和k. 第二行到第n+1行,每行一个正整数Ai. 输出格式: 一个非负整数. 输入输出样例 输入样例#1: 3

洛谷P2717 寒假作业

题目:https://www.luogu.org/problemnew/show/2717 题目背景 zzs和zzy正在被寒假作业折磨,然而他们有答案可以抄啊. 题目描述 他们共有n项寒假作业.zzy给每项寒假作业都定义了一个疲劳值Ai,表示抄这个作业所要花的精力.zzs现在想要知道,有多少组连续的寒假作业的疲劳值的平均值不小于k? 简单地说,给定n个正整数A1,A2,A3,...,An,求出有多少个连续的子序列的平均值不小于k. 输入输出格式 输入格式: 第一行两个正整数,n和k. 第二行到第

数学方法模拟(洛谷1017 进制转换NOIp2000提高组第一题)

我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1*10^2+2*10^1+3*10^0这样的形式. 与之相似的,对二进制数来说,也可表示成每个二进制数码乘以一个以该数字所处位置的(值-1)为指数,以2为底数的幂之和的形式.一般说来,任何一个正整数R或一个负整数-R都可以被选来作为一个数制系统的基数.如果是以R或-R为基数,则需要用到的数码为 0,1,....R-1.例如,当R=7时,所需用到

洛谷P1879 [USACO06NOV]玉米田Corn Fields【状压DP】题解+AC代码

题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can't b

洛谷 P1835 素数密度_NOI导刊2011提高(04)题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1835 题目描述 给定区间[L,R](L≤R≤2147483647,R-L≤1000000),请计算区间中素数的个数. 输入输出格式 输入格式: 两个数L和R. 输出格式: 一行,区间中素数的个数. 输入输出样例 输入样例#1: 2 11 输出样例#1: 5 分析:裸的区间素数筛.代码中有详细注释(其中区间素数筛函数大部分借用了<挑战程序

洛谷 p1164 小A点菜 【dp(好题)】 || 【DFS】

题目链接:https://www.luogu.org/problemnew/show/P1164 题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家--餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:"随便点". 题目描述 不过uim由于买了一些辅(e)辅(ro)书,口袋里只剩M元(M<=10000). 餐馆虽低端,但是菜品种类不少,有N种(N<=100),第i种卖ai元(ai<=1000).由于是很低端的餐馆,所以每种菜

洛谷P2420 让我们异或吧

P2420 让我们异或吧 161通过 450提交 题目提供者该用户不存在 标签洛谷原创云端↑ 难度普及/提高- 时空限制1s / 128MB 提交  讨论  题解 最新讨论更多讨论 倍增可做的吧 玄学 更改根节点得分不一样- 这题面似乎对一些群体不太友- 这题为什么没数据 C++选手注意了 题目描述 异或是一种神奇的运算,大部分人把它总结成不进位加法. 在生活中-xor运算也很常见.比如,对于一个问题的回答,是为1,否为0.那么: (A是否是男生 )xor( B是否是男生)=A和B是否能够成为情

洛谷P1991 无线通讯网

P1991 无线通讯网 170通过 539提交 题目提供者洛谷OnlineJudge 标签图论 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 怎么又炸了 为啥一直40!求解! UKE:invalid input file UKE Invalid Input File 未知错误 编译器不对 题目描述 国防部计划用无线网络连接若干个边防哨所.2 种不同的通讯技术用来搭建无线网络: 每个边防哨所都要配备无线电收发器:有一些哨所还可以增配卫星电话. 任意两个配备了一条卫星电话线路的哨所(两边都

高斯求和等差数列前缀和(洛谷1147 连续自然数和)

对一个给定的自然数M,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M. 例子:1998+1999+2000+2001+2002 = 10000,所以从1998到2002的一个自然数段为M=10000的一个解. 输入格式: 包含一个整数的单独一行给出M的值(10 <= M <= 2,000,000). 输出格式: 每行两个自然数,给出一个满足条件的连续自然数段中的第一个数和最后一个数,两数之间用一个空格隔开,所有输出行的第一个按从小到大的升序排列,对于给定的输入数据,保证至少有一