• luogu 3 月月赛 I & EE Round 1 Div.1


    这两天写题越来越有感觉了。

    Div.1 A

    一通乱猜,得到结论:当没有 (1) 的时候,答案是 (sum a_ia_{i+1}+min a_i)

    也就是从左往右消到最小值的左边,然后从右往左消到最小值的右边,最后消掉最小值。

    对原序列每个没有 (1) 的极长子段按刚才的式子算一下,然后把 (1) 的个数加上去,就好了。

    证明不难。

    Div.1 B

    这是大力出奇迹题,考场不敢开大数组获得整整 30 分!

    打表可知,(p|a_p) 当且仅当 (p|(k+1))

    证明:

    不会,咕咕咕。

    n 以内除给定数以外所有质数的乘积就是答案,线筛就好。

    据说 min25 能筛出来……先咕着。

    Div.1 C

    这题挺好的。

    先考虑没有 (-1) 的情况怎么做。

    首先根据输入的信息,容易知道到每个位置的时候单调栈里面都有哪些下标。

    考虑下标 (i<j_1<j_2<cdots <j_k) 中,(j_1,j_2,cdots,j_k) 曾经先后在单调栈里恰好压在 (i) 头顶上。

    那么必有 (p_i<p_{j_k}<p_{j_{k-1}}<cdots <p_{j_1})

    而只要一个排列满足以上条件,那么这个排列就一定是符合题意的。

    考虑构造。从 (0) 向在栈底待过的下标连边,对每个 (i) ,从 (i) 按顺序向 (j_1,j_2,cdots,j_k) 连边。

    你发现这样构成了一棵 ((n+1)) 个点的树。这棵树满足父亲小于儿子,且 对同一个父亲 编号大的儿子小于编号小的儿子。

    考虑到要字典序最小,那么编号小的 (i) 所获得的 (p_i) 要更小。

    对这棵树 DFS 一遍,每到一个点,从后往前确定每个儿子填什么,然后从前往后进儿子,递归执行。(具体参考代码)

    似乎还没说 (-1) 怎么做。设 (a_i=-1) ,那 (a_ileftarrow a_{i-1}+1) 就好了。容易证明这样没有问题。

    #include<cstdio>
    #include<vector>
    const int N=1e6+3;
    int n,a[N],st[N],s[N],k;
    std::vector<int>g[N];
    void Dfs(int i){
    	if(g[i].size())for(int j=g[i].size()-1;~j;j--)s[g[i][j]]=++k;
    	for(int j=0;j<g[i].size();j++){
    	  Dfs(g[i][j]);
    	}
    }
    signed main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    	  scanf("%d",a+i);
    	  if(a[i]<0)a[i]=a[i-1]+1;
    	}
    	for(int i=1;i<=n;i++){
    	  for(;k+1>a[i];--k);
    	  g[st[k]].push_back(i);
    	  st[++k]=i;
    	}
    	k=0;
    	Dfs(0);
    	for(int i=1;i<=n;i++)printf("%d ",s[i]);puts("");
    	return 0;
    }
    
  • 相关阅读:
    yii---where or该如何使用
    yii---获取当前sql语句
    yii---load怎么使用
    yii---往对象里面添加属性
    js---箭头函数
    yii---判断POST请求
    Atitit USRqc62204 证书管理器标准化规范
    Atitit  深入理解命名空间namespace  java c# php js
    atitit..代码生成流程图 流程图绘制解决方案 java  c#.net  php v2
    Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设
  • 原文地址:https://www.cnblogs.com/Camp-Nou/p/12444000.html
Copyright © 2020-2023  润新知