在cf水题の记录

CF1158C

题意:有排列p, 令\(nxt_i\)为\(p_i\)右侧第一个大于\(p_i\)的数的位置,若不存在则\(nxt_i=n+1\)

现在整个p和nxt的一部分丢失了,请根据剩余的nxt,构造出一个符合情况的p,输出任意一解。



使有解的充要条件是对于每一个i不存在\(j\in(i,nex_i)\)满足\(nex_j>nex_i\)

也就是说对于每个\(i\)向\(nxt_i\)连一条边,然后没有两条边相交

对于点\(i\)向\(nex_i\)和满足\(j<i \ \wedge nex_j>nex_i\)的最小的j连边

这样的话就是一个拓扑图

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#define M 2100001
#define N 500010
using namespace std;

int n,m,k,a[N],d[M],s[N],ver[N],t[N],T,B;
queue<int> q;

void ins(int now,int l,int r,int k,int x)
{
    if(l==r)
    {
        d[now]=k;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid) ins(now*2,l,mid,k,x);
    else ins(now*2+1,mid+1,r,k,x);
    d[now]=1;
}

int ask(int now,int l,int r,int L)
{
    if(l==r) return d[now];
    int mid=(l+r)>>1, k=0;
    if(L<=mid && d[now*2]) k=ask(now*2,l,mid,L);
    if(!k)return ask(now*2+1,mid+1,r,L);
    return k;
}

void rb(int now,int l,int r)
{
    if(!d[now]) return ;
    d[now]=0;
    if(l==r) return ;
    int mid=(l+r)>>1;
    rb(now*2,l,mid);
    rb(now*2+1,mid+1,r);
}

int main()
{
    scanf("%d",&T);
    for(T;T;T--)
    {
        B=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]==-1) a[i]=i+1;
        }

        for(int i=1;i<=n;i++)
        {
            k=ask(1,1,n+1,i+1);
            if(k && a[k]<a[i])
            {
                B=1;
                break;
            }
            ins(1,1,n+1,i,a[i]);
            s[a[i]]++;
            if(!k) continue;
            ver[i]=k; s[k]++;
        }

        if(!B)
        {
            for(int i=1;i<=n;i++) if(!s[i]) q.push(i);
            k=0;
            while(q.size())
            {
                int x=q.front(); q.pop();
                s[ver[x]]--; s[a[x]]--;
                if(!s[ver[x]]) q.push(ver[x]);
                if(!s[a[x]]) q.push(a[x]);
                t[x]=++k;
            }
            if(k!=n+1) B=1;
        }

        if(B) printf("-1");
        else for(int i=1;i<=n;i++) printf("%d ",t[i]);
        printf("\n");

        for(int i=1;i<=n+1;i++) t[i]=s[i]=ver[i]=a[i]=0;
        rb(1,1,n+1);
    }
}

原文地址:https://www.cnblogs.com/ZUTTER/p/10918412.html

时间: 2024-10-13 19:54:56

在cf水题の记录的相关文章

一道cf水题再加两道紫薯题的感悟

1. 遇到一个很大的数除以另一个数时,可以尝试把这个很大的数进行,素数因子分解. 2. 遇到多个数的乘积与另一个数的除法时,求是否能整除,可以先求每一个数与分母的最大公约数,最后若分母数字为1,则证明可整除.或者把分子上的每个数进行素数因子分解,分母上的数也进行素数因子分解,若分子上的与分母上相同素数因子进行比较,分子上的素数因子指数大于分母位置上的,则证明可整除. 3. 遇到乘法的时候注意越界问题. 4. 遇到求某一个区间内,满足某一特征的数的个数,而这个特征与因子,约数有关,尝试用埃筛的方法

openjudge dp水题记录

当发现自己竟然不会打dp的时候内心是崩溃的,然后按照一年前的刷题记录刷openjudge,然后发现自己准确率比一年前(刚学信竞两个月时)的准确率低得多,已经没救. 列一下最近打的几道sb题 2985:数字组合 描述有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式.如: n=5,5个数分别为1,2,3,4,5,t=5: 那么可能的组合有5=1+4和5=2+3和5=5三种组合方式.输入输入的第一行是两个正整数n和t,用空格隔开,其中1<=n<=20,表示正整数的个数,t为要求的和(1&

5.6水题记录

BZOJ 1029 确实是水题,由于人弱想了半天. 这题我以前好像做到过T^T... 原来贪心就可以了.据gty说,贪心策略: 能加则加 不能加尽量省出时间来. 感觉好奇葩,不知道为什么是对的...感觉正确性并不显然...先这么写了. #include <cstdio> #include <ext/pb_ds/priority_queue.hpp> #include <algorithm> __gnu_pbds::priority_queue<int,std::l

某5道CF水题

1.PolandBall and Hypothesis 题面在这里! 大意就是让你找一个m使得n*m+1是一个合数. 首先对于1和2可以特判,是1输出3,是2输出4. 然后对于其他所有的n,我们都可以非常快的找到一个最小的与它互质的质数p(考虑反证法),并且满足p<n. 这样就相当与解一个同余方程 n*m = p-1 (mod p) , 解出的m可以保证 n*m+1 是 p 的倍数,也就是合数了. 又因为gcd(p,n)==1,所以这个方程肯定有解,直接求一个 n 在mod p意义下的逆元然后乘

几道cf水题

题意:给你包含n个元素的数组和k种元素,要求k种元素要用完,并且每种颜色至少用一次,n个元素,如果某几个元素的值相同,这些个元素也不能染成同一种元素. 思路:如果元素个数n小于k或者值相同的元素的个数大于k,那么一定无解,输出-1.用一个num[a[i]]记录每种相同值的元素出现次数,若大于k,无解.这道题的关键在于如何处理值相同的这些元素,可以用一个二维数组f[i][j]来表示状态,其中i表示对应元素值,j代表颜色.只要对于相同的i,j值不同就可以了.每个元素用什么颜色记录在一个数组ans[i

水题记录

素数求和问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 现在给你N个数(0<N<1000),现在要求你写出一个程序,找出这N个数中的所有素数,并求和. 输入 第一行给出整数M(0<M<10)代表多少组测试数据每组测试数据第一行给你N,代表该组测试数据的数量.接下来的N个数为要测试的数据,每个数小于1000 输出 每组测试数据结果占一行,输出给出的测试数据的所有素数和 样例输入 3 5 1 2 3 4 5 8 11 12 13 14 15 16 1

一道cf水题

题意:输入数字n表示字符串中元素个数,字符串中只含有RGB三个字符,现在要求任意两个相同的字符他们的下标之差能整除3. 思路:任意两个相同的字符的下标能整除3,也就是任意三个为一组的字符串当中的字符不能相同,那么只要某一组字符确定了,那么字符串中所有字符也就确定了,我们不妨来枚举前三个字符可能的排列,只要第一组确定了,后面也就全部确定了(当时自己去字符串里面找第一个不重复的三个字符组不就是这个意思么).接下来第一组确定后,由于后面所有的字符都和它相同,所以我们只需要遍历一遍统计后面与他不对应的字

CF#FF(255)-div1-C【水题,枚举】

[吐槽]:本来没打算写这题的题解的,但惨不忍睹得WA了13次,想想还是记录一下吧.自己的“分类讨论能力”本来就很差. 刚开始第一眼扫过去以为是LIS,然后忽略了复杂度,果断TLE了,说起来也好惭愧,也说明有时候太懒得动脑了,总是习惯利用惯性思维,这不是一件好事. [题意]:给你大小为n的整型数组a[n],求这数组的一个子串,其中最多可以修改子串中的一个数字,使得到的子串是最长的严格递增的子串,输出该子串的长度 L. [思路]:O(n)复杂度,枚举断点情况.第0个和第n个位置默认为断点.(用ve[

CF 628A --- Tennis Tournament --- 水题

CF 628A 题目大意:给定n,b,p,其中n为进行比赛的人数,b为每场进行比赛的每一位运动员需要的水的数量, p为整个赛程提供给每位运动员的毛巾数量, 每次在剩余的n人数中,挑选2^k=m(m <=n)个人进行比赛,剩余的n-m个人直接晋级, 直至只剩一人为止,问总共需要的水的数量和毛巾的数量 解题思路:毛巾数很简单: n*p即可 水的数量:1,2,4,8,16,32,64,128,256,512,提前打成一个表, 根据当前剩余的人数n在表中二分查找最大的小于等于n的数,结果即为本次进行比赛