NEUQ网络赛小结

来源:互联网 发布:淘宝网机械水压开关 编辑:程序博客网 时间:2024/06/08 05:50

...感觉还是不太好。不管是心态还是别的什么。继续加油啊//

E

题目描述

给定一个数组,其中的元素满足非递减顺序。任意给定一个区间[i,j],求其中某个元素重复出现的最大次数。

输入

多组数据输入。每组数据的第一行包含两个整数n和q(1<=n,q<=100000),下一行包含n个整数a1,...,an(-100000<=ai<=100000,i∈{1,...,n}),用空格分隔,数列是升序的(ai<=ai+1)。接下来的q行,每行包含两个整数i和j(1<=i<=j<=n),表示给定区间[i,j]。
输入结束于0(自成一行)。

输出

对输入的q个区间,每个区间输出一个整数表示该区间内重复最多的元素出现的次数,用换行分隔。

样例输入

10 3-1 -1 1 1 1 1 3 10 10 102 31 105 100

样例输出

143

就是这几天写的线段树啊,刚开始都不确认,还是同个实验室别的队讲到才敢写,什么时候比赛不那么怂就好了。

代码:

#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn = 100000+10;int ls[maxn<<2],rs[maxn<<2],ms[maxn<<2];int n,m;int d[maxn];void build(int id,int l,int r){    ls[id] = rs[id] = ms[id] = 0;    if(l==r){ls[id] = rs[id] = ms[id] = 1;return;}    int m = l+r>>1;    build(id<<1,l,m);    build(id<<1|1,m+1,r);    ls[id] = ls[id<<1], rs[id] = rs[id<<1|1];    ms[id] = max(ms[id<<1],ms[id<<1|1]);    if(d[m] == d[m+1]) ms[id] = max(ms[id] , rs[id<<1] + ls[id<<1|1] );    if(ls[id] == m-l+1 && d[m] == d[m+1]) ls[id] += ls[id<<1|1];    if(rs[id] == r-m && d[m] == d[m+1]) rs[id] += rs[id<<1];}int q(int ql,int qr,int id,int l,int r){    if(qr < l || ql > r)    return 0;    if(l >= ql && r <= qr) return ms[id];    int m = l+r>>1;    if(qr <= m) return q(ql,qr,id<<1,l,m);    else if(ql > m) return q(ql,qr,id<<1|1,m+1,r);    else    {        int ans = q(ql,qr,id<<1,l,m);        ans = max(ans,q(ql,qr,id<<1|1,m+1,r));        if(d[m] == d[m+1])            ans = max(ans, min(m-ql+1,rs[id<<1]) + min(qr-m, ls[id<<1|1]));        return ans;    }}int main(){    while(~scanf("%d",&n))    {        if(n == 0) break;        scanf("%d",&m);        for(int i = 1; i <= n ; i++)            scanf("%d",&d[i]);        build(1,1,n);        for(int i = 0; i< m ;i ++)        {            int a,b;            scanf("%d%d",&a,&b);            printf("%d\n",q(a,b,1,1,n));        }    }    return 0;}



然后就gg了,但是其实矩阵快速幂是写出来了的,但是tle,当时脑子可能也是进了水,明明看过小优化,都不往上试,甚至比赛完了还在纠结,看到题解说滚动数组还真就去滚动数组了,最后发现重点还真不是滚动数组而是一个小优化。

就是在判断矩阵乘法的时候卡一下0,瞬间从1000多ms到了400ms。贴张图提醒自己一下,不要盲目瞎改。


题目描述

存在如下递推式:
F(n+1)=A1*F(n)+A2*F(n-1)+...+An*F(1)
求第K项的值对1000000007取模的结果

输入

单组测试数据

第一行输入两个整数 n , k (1<=n<=100,n<k<=10000000000)

第二行输入 n 个整数 F(1)   F(2)   ...   F(n)

第三行输入 n 个整数A1   A2   ...   An 

输出

输出一个整数

样例输入

2   31   23   4

样例输出

10
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <time.h>using namespace std;#define ll long longconst int maxn = 105;const ll mod = 1000000007;int n;ll k;ll f[maxn], a[maxn]; struct node{    ll mat[maxn][maxn];    node()    {        for(int i = 1; i <= n; i++)        for(int j = 1; j <= n; j++)            mat[i][j] = 0;    }}; node operator*(node a,node b){    node c;    for(int i = 1; i <= n ; i++)    for(int j = 1; j <= n ; j++)    for(int k = 1; k <= n ; k++)        if(a.mat[i][k] && b.mat[k][j])        c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j])%mod;    return c;} ll qp(ll k){    node ori,ans;    k = k-n;    for(int i = 1; i <= n; i++) ori.mat[1][i] = a[i];    for(int i = 2; i <= n; i++) ori.mat[i][i-1] = 1;    for(int i = 1; i <= n; i++) ans.mat[i][i] = 1;    while(k)    {        if(k&1) ans = ans*ori;        k = (k>>1);        ori = ori*ori;    }    ll res = 0;    for(int i = 1; i <= n ; i++)        res = (res + (ans.mat[1][i] * f[n-i+1])) % mod;    cout << res << endl;}int main(){    /*freopen("D://in.txt","r",stdin);    freopen("D://out.txt","w",stdout);     clock_t start_time=clock();    */    cin >> n >> k;    for(int i = 1; i <= n ; i++)        cin >> f[i];     for(int i = 1; i <= n ; i++)    {        cin >> a[i];    }     qp(k);     //clock_t end_time=clock();    //cout<<static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000<<endl;    return 0;}



阅读全文
0 0