COJ574 数字序列


试题描述

霸中智力测试机构的一项工作就是按照一定的规则删除一个序列的数字,得到一个确定的数列。陈思同学很渴望成为霸中智力测试机构的主管,但是他在这个工作上做的并不好,俗话说熟能生巧,他打算做很多练习,所以他希望你写一个程序来快速判断他的答案是否正确。


输入

第一行为一个整数m(1<=m<=1000000),
第二行包括m个用空格分开的整数ai(1<=ai<=1000000),组成了最初的序列,
第三行为一个整数n(1<=n<=1000000),表示n个陈思经过一系列删除得到的序列,每个序列两行,第一行给出长度L(1<=L<=m),然后下一行为L个由空格分开的整数bi(1<=bi<=1000000)。

输出

共n行,如果陈思的序列确实是由最初的序列删除一些数得到,就输出TAK,否则输出NIE。

输入示例

7
1 5 4 5 7 8 6
4
5
1 5 5 8 6
3
2 2 2
3
5 7 8
4
1 5 7 4

输出示例

TAK
NIE
TAK
NIE

其他说明

二分2083

对每个权值建立位置的集合,如果用vector要写二分,如果用平衡树就直接lower_bound了。

vector,用now表示当前位置+1,下同(3979ms)

#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}
const int maxn=1000010;
vector<int> T[maxn];
int main() {
    int n=read();
    rep(1,n) T[read()].push_back(i);
    int m=read();
    while(m--) {
        int k=read(),now=1,ok=1;
        rep(1,k) {
            int v=read();
            if(!T[v].size()||T[v][T[v].size()-1]<now) ok=0;
            else {
                int l=0,r=T[v].size()-1,mid;
                while(l<r) if(T[v][mid=l+r>>1]<now) l=mid+1; else r=mid;
                now=T[v][l]+1;
            }
        }
        if(ok) puts("TAK");
        else puts("NIE");
    }
    return 0;
}

偷懒用set结果T飞了(TLE)

#include<cstdio>
#include<cctype>
#include<set>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}
const int maxn=1000010;
set<int> T[maxn];
set<int>::iterator it;
int main() {
    int n=read();
    rep(1,n) T[read()].insert(i);
    int m=read();
    while(m--) {
        int k=read(),now=1,ok=1;
        rep(1,k) {
            int v=read();
            if(!T[v].size()) ok=0;
            else {
                it=T[v].lower_bound(now);
                if(it==T[v].end()) ok=0;
                else now=(*it)+1;
            }
        }
        if(ok) puts("TAK");
        else puts("NIE");
    }
    return 0;
}

STL太慢了,我们可以写一个数组,以权值为第一关键字,以位置为第二关键字排序,然后再上面继续二分。(827ms)

我竟然又WA了一发,越来越感觉要直播了。

#include<cstdio>
#include<cctype>
#include<set>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}
const int maxn=1000010;
struct Arr {
    int p,v;
    bool operator < (const Arr& ths) const {
        if(v!=ths.v) return v<ths.v;
        return p<ths.p;
    }
}A[maxn];
int L[maxn],R[maxn];
int main() {
    int n=read();
    rep(1,n) A[A[i].p=i].v=read();
    sort(A+1,A+n+1);
    int cur=1;
    rep(1,1000000) {
        if(A[cur].v!=i) continue;
        L[i]=cur;while(A[cur+1].v==i) cur++;R[i]=cur++;
    }
    int m=read();
    while(m--) {
        int k=read(),now=1,ok=1;
        rep(1,k) {
            int v=read();if(!L[v]||A[R[v]].p<now) ok=0;
            if(!ok) continue;
            int l=L[v],r=R[v],mid;
            while(l<r) if(A[mid=l+r>>1].p<now) l=mid+1; else r=mid;
            now=A[l].p+1;
        }
        if(ok) puts("TAK");
        else puts("NIE");
    }
    return 0;
}

时间: 2024-09-20 16:47:38

COJ574 数字序列的相关文章

BZOJ 1049 数字序列(LIS)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1049 题意:给出一个数列A,要求:(1)修改最少的数字使得数列严格递增:(2)在(1)的基础上使得修改的绝对值之和最小. 思路:对于第一问看起来像是求最长上升子 列,其实不是.我们想,若对于i<j,j能由i转移过来,那么需满足A[j]-A[i]>=j-i才行,这样我们发现只要A[j]-j& gt;=A[i]-i即可.因此令A[i]=A[i]-i,这样求LIS即可.对于第二问,

生成数字序列命令(7)

生成数字序列命令:seq,shuf 7.1.seq 功能:打印数字序列 语法:seq [OPTION]... LAST seq [OPTION]... FIRST LAST seq [OPTION]... FIRST INCREMENT LAST 常用选项: -f  使用printf样式格式 -s  指定分隔符,默认换行符\n -w  等宽,用0填充 示例: 数字序列: 方法1: [[email protected] ~]# seq 10 1 2 3 4 5 6 7 8 9 10 方法2: fo

笔试算法题(34):从数字序列中寻找仅出现一次的数字 &amp; 最大公约数(GCD)问题

出题:给定一个数字序列,其中每个数字最多出现两次,只有一个数字仅出现了一次,如何快速找出其中仅出现了一次的数字: 分析: 由于知道一个数字异或操作它本身(X^X=0)都为0,而任何数字异或操作0都为它本身,所以当所有的数字序列都异或操作之后,所有出现两次的数字异或操作之后的结果都为0,则最后剩下的结果就是那个仅出现了一次的数字: 如果有多个数字都仅仅出现了一次,则上述的异或操作方法不再适用:如果确定只有两个数字只出现了一次,则可以利用X+Y=a和XY=b求解: 解题: 1 int findSin

求一组数字序列的分布情况(java)

最近需要做一个正态分布的函数图像所以要处理一段double序列 写了这个算法  先上效果图: 核心思想: 1先根据步长计算每一个区间 2循环进行判断序列中每个数属于哪个区间 3用一个数组来保存每一个区间中 数的个数 这样就可以得到整个分布函数了 当然效率值得考虑 我的机器1百万以上的数据就会有问题了 这是一个double类型的例子 int型就更容易啦 上代码! 1 package com.huang.distribution; 2 3 import java.math.BigDecimal; 4

codevs 2622 数字序列

2622 数字序列 提交地址:http://codevs.cn/problem/2622/ 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description 给定一个长度为n的一个序列A1,A2,…,An,求序列中连续子序列的最大和. 例如:当输入为-5,3,5,7,-15,6,9,27,-36,10时,连续子序列6,9,27的和为42是最大值:而当序列变成-5,3,5,8,-15,6,9,27,-36,10时,连续子序列3,5,8,-15,6,9

【BZOJ 1049】 [HAOI2006]数字序列

1049: [HAOI2006]数字序列 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 979  Solved: 389 [Submit][Status] Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值. Output 第一行一个整数表示最少需要改变多少

[Jobdu] 题目1544:数字序列区间最小值

题目描述: 给定一个数字序列,查询任意给定区间内数字的最小值. 输入: 输入包含多组测试用例,每组测试用例的开头为一个整数n(1<=n<=100000),代表数字序列的长度.接下去一行给出n个数字,代表数字序列.数字在int范围内.下一行为一个整数t(1<=t<=10000),代表查询的次数.最后t行,每行给出一个查询,由两个整数表示l.r(1<=l<=r<=n). 输出: 对于每个查询,输出区间[l,r]内的最小值. 样例输入: 5 3 2 1 4 3 3 1

找出数组中最长的连续数字序列(JavaScript实现)

原始题目: 给定一个无序的整数序列, 找最长的连续数字序列. 例如: 给定[100, 4, 200, 1, 3, 2], 最长的连续数字序列是[1, 2, 3, 4]. 小菜给出的解法: 1 function maxSequence(array,step){ 2 var _array = array.slice(), //clone array 3 _step = 1, 4 _arrayTemp = [], 5 i = 0; 6 7 var parseLogic = { 8 //result c

【BZOJ】【1049】【HAOI2006】数字序列

DP 第一问比较水……a[i]-=i 以后就变成最长不下降子序列问题了,第二问这个结论好神奇,考试的时候怎么破?大胆猜想,不用证明?TAT 题解:http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411 没有将a[0]置为-INF在BZOJ上WA了……so sad…… 1 /************************************************************** 2 Problem: 10