【Henu ACM Round#15 F】Arthur and Questions

【链接】 我是链接,点我呀:)
【题意】

在这里输入题意

【题解】

a1+a2+...+aka1<ak+1

a2+a3+...+ak+1a2<ak+2

类似还可以推出
a3<ak+3
a4<ak+4
...

则有
a1<ak+1<a2k+1<a3k+1...
a2<ak+2<a2k+2<a3k+2...
...

也就是每隔k个要是递增的。
你的任务就是维护每隔k个数字递增。

我们先考虑a[1],a[1+k],a[1+2k],a[1+3k]...这个序列。
枚举所有不是问号的位置i,j(i < j) 且i+1..j-1之间的位置都是问号。

 首先判断i-j-1是否大于等于a[j]-a[i]-1
 因为如果不满足,显然这i-j-1个位置没办法按最小的递增顺序放满。肯定会不是严格递增的。
 因此直接输出无解

 接下来要考虑绝对值最小这个约束.来代替各个问号。

 如果a[i]>=0 且a[j]>=0
 那么按a[i]+1,a[i]+2..顺序递增代替问号就好
 a[i]<=0且a[j]<=0,就a[j]-(i-j-1),a[j]-(i-j-1)+1....顺序递增
 a[i]<0且a[j]>0的话,就从0的两边交替选数字就好,取出0两边交替的数字的最小值\(-\frac{(i-j-1)}{2}\),然后递增代替问号就可以。
 当然要大于a[i]且小于等于a[j]-(i-j-1)

15e8-(-15e8)会爆long long.....

【代码】

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5;
const int INF = 105e7;

int n,k,a[N+10],b[N+10];
char s[20];

int main(){
    #ifdef LOCAL_DEFINE
        freopen("rush_in.txt", "r", stdin);
    #endif
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> n >> k;
    for (int i = 1;i <= n;i++) {
        cin >> s;
        if (s[0]=='?'){
            a[i] = INF;
        }else {
            a[i] = atoi(s);
        }
    }

    for (int i = n+1;i <= n+k;i++) a[i] = INF+1;

    for (int i = 1;i <= k;i++){
        int tot = 0,prev = -INF;
        for (int j = i;j <= n+k;j+=k)
            if (a[j]==INF){
                tot++;
            }else{
                    if (a[j]- prev-1<tot){
                        return cout<<"Incorrect sequence"<<endl,0;
                    }

                    int s;
                    if (prev>=0)
                        s = prev+1;
                    else if (a[j]<=0) s = a[j]-tot;
                    else{
                        s = max(prev+1,min(-tot/2,a[j]-tot));
                    }

                    for (int kk = tot;kk >= 1;kk--){
                        a[j-k*kk] = s++;
                    }
                    prev = a[j];
                    tot=0;
                }
        }

    for (int i = 1;i <= n;i++)
        cout <<a[i]<<' ';

    return 0;
}

原文地址:https://www.cnblogs.com/AWCXV/p/8447059.html

时间: 2024-08-30 17:07:56

【Henu ACM Round#15 F】Arthur and Questions的相关文章

【Henu ACM Round#15 E】 A and B and Lecture Rooms

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 最近公共祖先. (树上倍增 一开始统计出每个子树的节点个数_size[i] 如果x和y相同. 那么直接输出n. 否则求出x和y的最近公共祖先.z (假定y的深度大于x [1]如果z等于x或y中的一个. 那么久就找到x..y的路径(长度设为L)中的中点u. 显然,u和它的其他len-1个子树上的任意一个节点都是可行的(除了那个包含y的子树 设_get(x,step)表示x节点往上走step步到达的节点 则输出_sum[中点]-_s

【Henu ACM Round#15 A】 A and B and Chess

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 统计大写和小写的个数. 比较答案.输出即可. [代码] #include <bits/stdc++.h> using namespace std; string s[10]; map<char,int> dic; int inc[300]; int main() { for (int i = 0;i < 8;i++) cin >> s[i]; for (int i = 0;i < 8;i++

【Henu ACM Round#15 C】 A and B and Team Training

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举第一种方法. 剩下的全都个第二种方法. 看看能组成多少个队伍就可以了. [代码] #include <bits/stdc++.h> #define ll long long using namespace std; int n,m; int main() { ios::sync_with_stdio(0),cin.tie(0); cin >> n >> m; int ans = 0; for(int

【Henu ACM Round#18 B】Modulo Sum

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] m比较小 <=1000 a[i]直接看成a[i]%m就可以了. 有n个0..999之间的整数.. 如果有一个0那么就直接输出Yes. 否则要用那些数字凑0 则用cnt[0..999]记录每个数字出现的个数. 即n个物品,每个物品cnt[i]个. 然后凑和为0 ->多重背包. 但每个物品的数量可能很多. 所以加一个二进制优化就好了. 把每个物品的数量转化成二进制. 转换成01背包的问题. (物品的数目大概在1000*log2(1

【Henu ACM Round#20 D】 Devu and Partitioning of the Array

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 一开始所有的数字单独成一个集合. 然后用v[0]和v[1]记录集合的和为偶数和奇数的集合它们的根节点(并查集 然后先让v[0]的大小变成p //奇数+偶数是奇数 //奇数+奇数是偶数 //偶数+偶数是偶数 如果v[0].size < p 那么随便让两个和为奇数的集合,让他们合并在一起,加入到偶数集合中,那么v[0].size++,v[1].size-=2了 如果v[0].size > p 那么有两种方法 ?1.让两个偶数集合合

【Henu ACM Round #13 C】 Ebony and Ivory

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 先求出c-bx的所有可能 ->存在map里面 然后枚举y看看ay在不在map里面 在的话就有解. 这样复杂度是\(O(N*log_2N)\)的 比直接两层循环枚举的\(O(N^2)\)复杂度要来的好 这种方法也叫"中途相遇法" [代码] #include <bits/stdc++.h> #define ll long long using namespace std; ll a,b,c; map<

【Henu ACM Round #13 B】Spider Man

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 会发现每个环可以操作的次数是固定的. (环的大小-1 也就是说一旦环确定了.其实结果就已经确定了. 则直接看操作总数的奇偶性就可以了. [代码] #include <bits/stdc++.h> #define long long using namespace std; int n,x; int main(){ #ifdef LOCAL_DEFINE freopen("rush_in.txt", &quo

【Henu ACM Round #13 D】A Trivial Problem

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 123...n中末尾0的个数 只会由素因子2和5的个数决定且等于 Min{cnt[2],cnt[5]} 且素因子2的个数一定会比5多; 所以n!的末尾0的个数 等于for (int i = 1;i <= n;i++)中所有i的5因子的个数和 枚举一下就好 [代码] #include <bits/stdc++.h> using namespace std; const int N = 1e7; int n; vector&

【Henu ACM Round #13 E】Spy Syndrome 2

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 对m个串建立一棵字典树. 然后对主串. 尝试从第一个位置开始.在字典树中尝试匹配 如果匹配到了位置i 就再从位置i+1开始尝试匹配 (这时又重新从根节点开始重新匹配 每次匹配最多只要往下走50步. 写个递归的过程就好. [代码] #include <bits/stdc++.h> using namespace std; const int N = 1e6; const int NN = 1e4; const int M = 1