浙大2018省赛——重现赛(The 15th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple)

题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=378

简单题就不写了。

============================================

D、Sequence Swapping

E、LIS

一、题意  

  题目背景为LIS。现在已知$dp$数组,给定所有元素的上下界,要求构造满足条件的数组。Special Judge。

二、思路

  不妨假设输入数据为$a[i]$。定义$c[i]$,表示:距离$a[i]$最近的且等于$a[i]-1$的元素位置。当$a[i]=1$时,那$c[i]$就随便了。$i$位置的上下界分别定义为$ub[i]$和$lb[i]$。

  接下来,枚举所有的$dp$值,最小$1$,最大$n$。对于当前枚举的值$i$,找出$i$在$a$数组中的所有出现位置(可$O(n)$时间预处理出来),对于出现位置$p$,下标为$p$处的答案应该为:

  如果$a[p]=1$,$ans[p]=max(lb[p],max{ans[j]}(p<j<=n&&a[j]=a[p]))$;

  否则,$ans[p]=max(lb[p]max{ans[j]}(p<j<=n&&a[j]=a[p]), ans[c[p]]+1)$;

  /*********************LaTeX解析不出来,难受,TT_TT*******************************/

  此外,这题的上界在此思路中是没用的。因为这种思路可保证所求答案一定在上界内。

  注意,这题卡常非常严重。清空记录位置的容器时,循环上界用$n$,别用$MAXN$。

三、代码

  

/********************template head********************/
#include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define mk(x, y) make_pair(x, y)
#define pln() putchar('\n')
#define cln() (cout << '\n')
#define fst first
#define snd second
#define MOD 1000000007LL
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int MAXN = 1e5 + 10;

template <class T> inline void read(T &x) {
    int t;
    bool flag = false;
    while((t = getchar()) != '-' && (t < '0' || t > '9')) ;
    if(t == '-') flag = true, t = getchar(); x = t - '0';
    while((t = getchar()) >= '0' && t <= '9') x = x * 10 + t - '0';
    if(flag) x = -x;
}

template<class T> T gcd(T a, T b) {
    return b ? gcd(b, a % b) : a;
}

template<class T> T modpow(T a, T x, T mod) {
    T res = T(1);
    while(x > 0) {
        if(x & 1)res = (res * a) % mod;
        a = (a * a) % mod;
        x >>= 1;
    }
    return res;
}
/********************template head********************/


int n, a[MAXN], b[MAXN], c[MAXN], lb[MAXN], ub[MAXN], ans[MAXN];
vector<int> vs[MAXN];
int main() {
#ifndef ONLINE_JUDGE
   // freopen("input.txt", "r", stdin);
#endif // ONLINE_JUDGE
    int T;
    for(read(T); T--;) {
        read(n);
        for(int i = 1; i <= n; ++i)vs[i].clear();
        for(int i = 1; i <= n; ++i) {
            read(a[i]);
            b[a[i]] = i;
            c[i] = b[a[i] - 1];
            vs[a[i]].pb(i);
        }
        for(int i = 1; i <= n; ++i)read(lb[i]), read(ub[i]);
        for(int i = 1; i <= n; ++i) {
            int yb = -1;
            for(int j = vs[i].size() - 1; j >= 0; --j) {
                int p = vs[i][j];
                ans[p] = max(lb[p], yb);
                if(a[p] != 1)ans[p] = max(ans[p], ans[c[p]] + 1);
                yb = ans[p];
            }
        }
        for(int i = 1; i <= n; ++i)printf("%d%c", ans[i], i == n ? '\n' : ' ');
    }
    return 0;
}

 

F、Now Loading!!!

一、思路

  预处理出$\frac{a[i]}{j}(1 \le i \le n, 1 \le j \le 30)$的前缀和。注意$j$的最大值,如果前缀和的类型为long long,$j$的上界取为$31$,会MLE。当然,可以用int,然后,在预处理前缀和的时候对$10^9$取模。但是,要注意,在求区间和的时候,要保证区间和为正。

  然后,倍增+二分即可。

二、代码实现

 

/*--------------template head----------------*/
#include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define mk(x, y) make_pair(x, y)
#define pln() putchar('\n')
#define cln() (cout << '\n')
#define fst first
#define snd second
#define MOD 1000000000LL
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int MAXN = 1e5 + 10;

template <class T> inline void read(T &x) {
    int t;
    bool flag = false;
    while((t = getchar()) != '-' && (t < '0' || t > '9')) ;
    if(t == '-') flag = true, t = getchar(); x = t - '0';
    while((t = getchar()) >= '0' && t <= '9') x = x * 10 + t - '0';
    if(flag) x = -x;
}

template<class T> T gcd(T a, T b){
    return b ? gcd(b, a % b) : a;
}

template<class T> T modpow(T a, T x, T mod){
    T res = T(1);
    while(x > 0){
        if(x & 1)res = (res * a) % mod;
        a = (a * a) % mod;
        x >>= 1;
    }
    return res;
}
/*--------------template head----------------*/
int a[500010],n,m;
LL data[31][500010];
LL qzh(int ai,int aa,int b)
{
    return data[ai][b]-data[ai][aa-1];
}
int main() {
    //freopen("input.txt", "r", stdin);
    int T;
    LL p;
    cin>>T;
    while(T--)
    {
        LL ans=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++) read(a[i]);
        sort(a+1,a+n+1);
        for(int i=1;i<=30;i++)
        {
            data[i][1]=a[1]/i;
            for(int j=2;j<=n;j++) data[i][j]=data[i][j-1]+a[j]/i;
        }
        for(int i=1;i<=m;i++)
        {
            LL sum=0;
            read(p);
            int bg=1,ed=1;
            LL ap=1;
            int qz=0;
            while(++qz)
            {
               if(ap>a[n]) break;
               ap*=p;
               ed=upper_bound(a+1,a+1+n,ap)-a;
               sum=sum+qzh(qz,bg,ed-1);
               //cout<<ap<<" "<<bg<<" "<<ed-1<<endl;
               sum%=MOD;
               bg=ed;
            }
            sum*=i;
            sum%=MOD;
            ans=ans+sum;
            ans%=MOD;
        }
        cout<<ans<<"\n";
    }
    return 0;
}

 

posted on 2018-05-02 20:50  鹤鸣于九皋,声闻于天  阅读(252)  评论(0编辑  收藏  举报

导航