多校第三场第一题:Problem A. Ascending Rating

Problem A. Ascending Rating
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1339 Accepted Submission(s): 362

Problem Description
Before the start of contest, there are n ICPC contestants waiting in a long queue. They are labeled by 1 to n from left to right. It can be easily found that the i-th contestant’s QodeForces rating is ai.
Little Q, the coach of Quailty Normal University, is bored to just watch them waiting in the queue. He starts to compare the rating of the contestants. He will pick a continous interval with length m, say [l,l+m−1], and then inspect each contestant from left to right. Initially, he will write down two numbers maxrating=0 and count=0. Everytime he meets a contestant k with strictly higher rating than maxrating, he will change maxrating to ak and count to count+1.
Little T is also a coach waiting for the contest. He knows Little Q is not good at counting, so he is wondering what are the correct final value of maxrating and count. Please write a program to figure out the answer.

Input
The first line of the input contains an integer T(1≤T≤2000), denoting the number of test cases.
In each test case, there are 7 integers n,m,k,p,q,r,MOD(1≤m,k≤n≤107,5≤p,q,r,MOD≤109) in the first line, denoting the number of contestants, the length of interval, and the parameters k,p,q,r,MOD.
In the next line, there are k integers a1,a2,…,ak(0≤ai≤109), denoting the rating of the first k contestants.
To reduce the large input, we will use the following generator. The numbers p,q,r and MOD are given initially. The values ai(k < i ≤ n) are then produced as follows :
ai=(p×ai−1+q×i+r)modMOD

It is guaranteed that ∑n≤7×107 and ∑k≤2×106.

Output
Since the output file may be very large, let’s denote maxratingi and counti as the result of interval [i,i+m−1].
For each test case, you need to print a single line containing two integers A and B, where :
AB==∑i=1n−m+1(maxratingi⊕i)∑i=1n−m+1(counti⊕i)

Note that “⊕” denotes binary XOR operation.

Sample Input
1
10 6 10 5 5 5 5
3 2 2 1 5 7 6 8 2 9

Sample Output
46 11

这道题靠的是数据结构,没有接触过这样的类型题,所以思考很困难,有的时候正向思维比较难想,反过来想就好弄多了
题解:
按照 r 从 m 到 n 的顺序很难解决这个问题。
考虑按照 r 从 n 到 m 的顺序倒着求出每个区间的答案。
按照滑窗最大值的经典方法维护 a 的单调队列,那么队列 中的元素个数就是最大值的变化次数
O(n)的复杂度解决

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int maxn=1e7+5;
typedef struct Node{
    int value,pos;
    Node(){}
    Node(int v,int p){value = v;pos = p;}
}Node;
int a[maxn];
Node node[maxn];
LL A,B;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,k,p,q,r,mod;
        scanf("%d %d %d %d %d %d %d",&n,&m,&k,&p,&q,&r,&mod);
        A = 0;
        B = 0;
        for(int i = 1;i <= k;++i)
        {
            scanf("%d",&a[i]);
        }
        for(int i = k + 1;i <= n;++i)
        {
            a[i] = (1LL * p * a[i - 1] + 1LL * q * i + r) % mod;
        }
        int head = 1,tail = 0;
        for(int i = n;i >= 1;--i)
        {
            //删尾
            while(head <= tail && node[tail].value <= a[i]) tail--;
            //得到最优解并插入
            node[++tail] = Node(a[i],i);
            //去头
            while(node[head].pos - i >= m) head++;
            if(i <= n - m + 1){
                //printf("%d %d %d\n",node[head].value,tail - head + 1,index);
                A += (LL)(node[head].value ^ i);
                B += (LL)((tail - head + 1) ^ i);
            }
        }
        printf("%lld %lld\n",A,B);
    }
    return 0;
}







转载:https://blog.youkuaiyun.com/a_bright_ch/article/details/77076228
单调队列的介绍与使用:
单调队列顾名思义就是一个有规律的队列,这个队列的规律是:所有在队列里的数都必须按递增(或递减)的顺序列队,如果真有这么一个队列,那么队列的头是不是就是最小(或最大)的呢?

可以解决区间段内的最大值

例题:(来源:caioj 1172)

给定一个n个数的数列,从左至右输出每个长度为m的数列段内的最大数。

解法1:
如果按照常规方法,我们在求f[i]即i~i+m-1区间内的最值时,要把区间内的所有数都访问一遍,时间复杂度约为O(nm)。有没有一个快一点的算法呢?

解法2:
我们知道,上一种算法有一个地方是重复比较了,就是在找当前的f(i)的时候,i的前面k-1个数其它在算f(i-1)的时候我们就比较过了。那么我们能不能保存上一次的结果呢?当然主要是i的前k-1个数中的最大值了。答案是可以,这就要用到单调递减队列。

使用单调队列就涉及到去头和删尾:

1、队列的头一定是在一段时间前就加入了队列,现在的队列头会不会离开了我们处理的区间呢?如果它离我们正在处理的i太远了,我们就要把它去掉,去除冗杂的信息。

2、为了保证队列的递减性,在从列队尾新插入元素v时,要考虑队列尾的值是否大于v,如果是,队列呈现 队列尾-1的值 > 队列尾的值 > v ,此时队列递减性没有消失;如果不是,队列呈现 队列尾-1的值 > 队列尾的值 < v ,队列递减性被打破。

为了维护递减性,我们做如下考虑:v是最新值,它的位置是目前最靠后的,它可成为以后的最大值,必须留下;队列尾-1的值与v大小不定,不能冒然删去它;队列尾的值夹在v和队列尾-1之间,它不但不是最大值,对于以后的情况又不如v优,因为v相比队列尾更靠后(v可以影响到后m个值,队列尾只能影响到从它的位置往后数m-1个值),而且值更大,所以删队列尾是必定的。

在维护好一个 区间正确、严格递减 的单调递减队列后,队列头就是当前区间的最大值了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int a[200000];
struct node
{
    int x,p;
    node(){}
    node(int xx,int pp){x=xx;p=pp;}
}list[200000];

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    int head=1,tail=1;
    list[1]=node(a[1],1);
    for(int i=2;i<=n;i++)
    {
        while(head<=tail&&list[tail].x<=a[i]) tail--;//删尾
        list[++tail]=node(a[i],i);//得到最优解并插入
        while(i-list[head].p>=m) head++;//去头
        if(i>=m) printf("%d\n",list[head]);
    }
    return 0;
}

整理归纳单调队列的定义:

1、维护区间最值;
2、去除冗杂状态;
3、保持队列单调(最大值是单调递减序列,最小值是单调递增序列);
4、最优选择在队首。

整理归纳单调队列的使用方法:

1、维护队首(对于上题就是如果你已经是当前的m个之前那你就可以被删了) ;
2、在队尾插入(每插入一个就要从队尾开始往前去除冗杂状态) ;
3、取出需要的最优解(队列头的值即是);
4、借助最优解,得到目前所求的最优解(通常此处插入DP方程)。

单调队列的原理:

在处理f[i]时,去除冗杂、多余的状态,使得每个状态在队列中只会出现一次;同时维护一个能瞬间得出最优解的队列,减少重新访问的时间;在取得自己所需的值后,为后续的求解做好准备。

<think>好的,我现在需要帮助用户检查他们提供的Power Apps公式是否有错误。用户给出的公式是: SortByColumns( Filter( 'IPQA PLAY BOOK content table', 'Classification name'.Value = Label12_1.Text ), "ID", SortOrder.Ascending ), "ID", SortOrder.Ascending, 500 // 限制返回行数 ) 首先,我要理解这个公式的结构和各个部分的作用。看起来用户是在使用SortByColumns和Filter函数来处理数据。让我逐步拆解分析。 首先,最内层是Filter函数,它作用于数据源'IPQA PLAY BOOK content table',筛选条件是'Classification name'.Value等于Label12_1.Text的控件值。这部分看起来没问,Filter函数的第一个参数是数据源,第二个是条件,语法正确。 接下来,Filter的结果作为SortByColumns的第一个参数。SortByColumns通常的语法是SortByColumns(数据源, 列名, 排序方式)。这里用户给的是SortByColumns(Filter(...), "ID", SortOrder.Ascending),这部分也是正确的,按ID升序排列筛选后的结果。 但问可能出在后面的参数。用户接着又写了一次"ID", SortOrder.Ascending, 500。这里看起来像是传了参数。标准的SortByColumns函数最接受三个参数:数据源、列名、排序方式。而用户在这里传入了四个参数:前面的SortByColumns结果、"ID"、SortOrder.Ascending,以及额外的500。这显然不符合SortByColumns的语法,会导致错误。 然后,用户可能混淆了SortByColumns和另一个函数,比如可能想用Top函数来限制返回行数,但写法不正确。正确的做法应该是先排序,然后使用FirstN或者LastN来限制行数。例如,FirstN(SortByColumns(...), 500)。 或者,用户可能误以为SortByColumns有一个参数可以限制行数,但实际上并没有。所以需要在SortByColumns之后使用FirstN函数来限制结果数量。因此,正确的组合可能是将SortByColumns和FirstN结合使用。 另外,检查参数顺序是否正确。原公式中的结构是SortByColumns( Filter(...), "ID", SortOrder.Ascending ), "ID", SortOrder.Ascending, 500。这可能意味着用户嵌套了两个SortByColumns,但实际结构混乱。可能用户的本意是先筛选,然后排序,再限制行数,但语法错误导致参数过。 总结可能的错误点: 1. SortByColumns函数被错误地传递了四个参数,而它只需要三个。 2. 500作为第四个参数无效,可能需要使用其他函数来限制行数。 3. 可能存在重复的排序参数,结构混乱。 因此,正确的公式应该调整参数,并添加FirstN函数来限制行数。例如: FirstN( SortByColumns( Filter( 'IPQA PLAY BOOK content table', 'Classification name'.Value = Label12_1.Text ), "ID", SortOrder.Ascending ), 500 ) 或者如果用户希望先排序两次(虽然不太可能),但更可能是误用了参数。需要根据实际需求调整结构。</think>您提供的公式存在以下问: **错误分析:** $$SortByColumns( Filter(), "ID", SortOrder.Ascending, 500 )$$ 1. **参数数量错误**:`SortByColumns`函数最接受3个参数(数据源、列名、排序方式),但您传递了4个参数(最后一个500是无效参数) 2. **行数限制语法错误**:Power Apps中限制返回行数需要使用`FirstN`或`LastN`函数,不能直接在`SortByColumns`中添加数字参数 **修正建议:** ```powerapps FirstN( SortByColumns( Filter( 'IPQA PLAY BOOK content table', 'Classification name'.Value = Label12_1.Text ), "ID", SortOrder.Ascending ), 500 ) ``` **修正说明:** 1. 使用$FirstN$函数包裹排序结果,实现行数限制 2. 保持$SortByColumns$的标准参数结构: - 第1参数:筛选后的数据表 - 第2参数:排序字段名"ID" - 第3参数:排序方向$SortOrder.Ascending$ 3. 最终返回前500条记录 **公式验证方法:** 1. 在Power Apps Studio的公式栏输入时,观察智能提示是否正常显示参数 2. 测试运行时检查: - 筛选条件是否生效(分类名称匹配) - 排序结果是否正确(按ID升序排列) - 是否只返回最500条记录 **扩展建议:** 如果需要更复杂的排序规则,可以改用: $$Sort( FirstN( Filter(...), 500 ), ID, Ascending )$$ 这种写法将过滤、限制行数和排序分步骤执行,可读性更好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值