「SCOI2007」降雨量

P2471 [SCOI2007]降雨量 https://www.luogu.com.cn/problem/P2471

明明是st表的题;

但是却在st表之外的细节地方花了好久时间orz;

关于st表的原理可以看这个: 

算法学习笔记(12): ST表 - 知乎 (zhihu.com)

 (或者自己把st表什么的打印一下看看就明白了)

题意:求 x 是自从 y 以来 降水量最多的年份 这句话对不对

思路:

输入(年份) y x

1.假如y和x的降水量都不知道——maybe;

2.假如y降水量不知道,x降水量知道:

——查询y到x之间 有无 年份z的降水量 大于或等于 x的降水量—— 若有,false;若无,maybe;

3.假如y降水量知道,x降水量不知道:

——查询y到x之间 有无 年份z的降水量 大于或等于 y的降水量—— 若有,false;若无,maybe;

4.假如y和x的降水量都知道:

        (0)若y的降水量大于x的降水量——false;

        (1)y到x之间所有年份的降水量都已知:

                ——查询y到x之间 有无 年份z的降水量 大于或等于 x的降水量

                        ——若有,false;若无,true;

        (2)y到x之间有年份的降水量未知:

                ——查询y到x之间 有无 年份z的降水量 大于或等于 x的降水量

                        ——若有,false;若无,maybe;

以上是判断条件;


那么问题是:怎么判断y和x之间有没有未知年份??

年份x,y的数据范围是\left | x \right |\leq1E9,所以就离散化了;

【用vis数组看这一年有没有降水量可能MLE先不说,好像也不能一下子看出来中间有没有年份降水量是0,暴力会TLE】

方法一vector(没试过,摊)

考虑用 vector[第几个]=年份 的方法,年份的降水量是st表中的 st[i][0] ;

看yx年份有没有降水量——用vector+lower_bound看找到的年份是不是xy的;

看yx中间年份有没有降水量——看xy的年份差是否等于xy的序号差;

查中间最值——用lower_bound找好后直接st表查;

方法二map(代码如下):

考虑用 map[年份]=第几个 的方法,年份的降水量是st表中的 st[i][0] ;

看yx年份有没有降水量——用map[年份]是否为0 看或者用count看;

看yx中间年份有没有降水量——看xy的年份差是否等于xy的序号差;

查中间最值——用lower_bound找好后直接st表查;


代码如下:

注意:

low_bound找到end的地方要判断一下!

st表查询时x-1到y+1之间的判断!如果x-1==y,那么中间值就是0!

找年份的时候,low_bound是找不小于这个年份的!!

#include<bits/stdc++.h>
using namespace std;
  inline int read() {
  char c=getchar();
  int x=0,f=1;
  while (c<'0'||c>'9'){
    if (c=='-') f=-1;
    c=getchar();
  }
  while (c >='0'&&c<='9') {
    x=x*10+c-'0';
    c=getchar();
  }
  return x*f;
}
int lg[50006];
int f[50006][20],q;
map <int,int> mp;
int query(int x, int y) {
    int l=lg[y-x+1];
	return max(f[x][l],f[y-(1<<l)+1][l]);
    }
int main()
{
    int n;n=read();
	lg[1]=0;
	for (int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
	for (int i=1;i<=n;i++){int x;x=read();mp[x]=i;f[i][0]=read();}
	for (int j=1;j<=lg[n];j++)
			for (int i=1;i<=n-(1<<j)+1;i++){
					f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
			}
    int m;
    m=read();
    while(m--){
		int x,y;
		scanf("%d%d",&y,&x);//year
		if(y>=x){puts("false");continue;}
		if(!mp.count(y)&&!mp.count(x)){puts("maybe");continue;}
        map<int,int>::iterator itx=mp.lower_bound(x),ity=mp.lower_bound(y);
		if(!mp.count(y)&&mp.count(x))
        {
            int numy=ity->second;
            int q=numy<=mp[x]-1?query(numy,mp[x]-1):0;
            if(q>=f[mp[x]][0]){puts("false");continue;}
            else {puts("maybe");continue;}
        }
        if(mp.count(y)&&!mp.count(x))
        {
            int numx=itx==mp.end()?mp.size():itx->second-1;
            int q=mp[y]+1<=numx?query(mp[y]+1,numx):0;
            if(q>=f[mp[y]][0]){puts("false");continue;}
            else {puts("maybe");
            continue;}
        }
        if(f[mp[x]][0]>f[mp[y]][0]){puts("false");continue;}
		if(y-x==mp[y]-mp[x])
        {
            int q=mp[y]+1<=mp[x]-1?query(mp[y]+1,mp[x]-1):0;
            if(q>=f[mp[x]][0]){puts("false");continue;}
            else {puts("true");continue;}
        }
        else {
            int q=mp[y]+1<=mp[x]-1?query(mp[y]+1,mp[x]-1):0;
            if(q>=f[mp[x]][0]){puts("false");continue;}
            else {puts("maybe");continue;}
        }
    }
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中描述了一个幼儿园里分配糖果的问题,每个小朋友都有自己的要求。问题的输入包括两个整数NN和KK,表示幼儿园里的小朋友数量和要满足的要求数量。接下来的KK行表示小朋友们的要求,每行有三个数字,XX,AA,BB。如果X=1,表示第AA个小朋友分到的糖果必须和第BB个小朋友分到的糖果一样多;如果X=2,表示第AA个小朋友分到的糖果必须少于第BB个小朋友分到的糖果;如果X=3,表示第AA个小朋友分到的糖果必须不少于第BB个小朋友分到的糖果;如果X=4,表示第AA个小朋友分到的糖果必须多于第BB个小朋友分到的糖果;如果X=5,表示第AA个小朋友分到的糖果必须不多于第BB个小朋友分到的糖果。这个问题可以被看作是一个差分约束系统的问题。 具体地说,可以使用差分约束系统来解决这个问题。差分约束系统是一种通过给变量之间的关系添加约束来求解最优解的方法。对于这个问题,我们需要根据小朋友们的要求建立约束条件,并通过解决这个约束系统来得出最小的糖果数量。 在问题的输入中,X的取值范围为1到5,分别对应不同的关系约束。根据这些约束,我们可以构建一个差分约束图。图中的节点表示小朋友,边表示糖果数量的关系。根据不同的X值,我们可以添加相应的边和权重。然后,我们可以使用SPFA算法(Shortest Path Faster Algorithm)来求解这个差分约束系统,找到满足所有约束的最小糖果数量。 需要注意的是,在读取输入时需要判断X和Y是否合法,即是否满足X≠Y。如果X=Y,则直接输出-1,因为这种情况下无法满足约束条件。 综上所述,为了满足每个小朋友的要求,并且满足所有的约束条件,我们可以使用差分约束系统和SPFA算法来求解这个问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【差分约束系统】【SCOI2011】糖果 candy](https://blog.csdn.net/jiangzh7/article/details/8872699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [P3275 [SCOI2011]糖果(差分约束板子)](https://blog.csdn.net/qq_40619297/article/details/88678605)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值