HDU 5860 Death Sequence

用线段树可以算出序列。然后o(1)询问。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-8;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar(); x = 0;while(!isdigit(c)) c = getchar();
    while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar();  }
}

const int maxn=3000010;
int T,n,k,q,sz,cnt,p;
int s[4*maxn],ans[maxn];

void build(int l,int r,int rt)
{
    s[rt]=0;
    if(l==r){ s[rt]=1; return;}
    int m=(l+r)/2;
    build(l,m,2*rt);
    build(m+1,r,2*rt+1);
    s[rt]=s[2*rt]+s[2*rt+1];
}

void get(int sum,int l,int r,int rt)
{
    if(l==r) { s[rt]=0, p=l; return; }
    int m=(l+r)/2;
    if(s[2*rt]>=sum) get(sum,l,m,2*rt);
    else get(sum-s[2*rt],m+1,r,2*rt+1);
    s[rt]=s[2*rt]+s[2*rt+1];
}

int main()
{
   // File();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&k,&q);
        build(1,n,1);

        sz=n; cnt=0;
        while(sz>0)
        {
            int mx=(sz-1)/k;
            for(int i=0;i<=mx;i++)
            {
                int sum=1+i*k-i;
                get(sum,1,n,1); ans[++cnt]=p; sz--;
            }
        }
        for(int i=1;i<=q;i++)
        {
            int x; scanf("%d",&x);
            printf("%d\n",ans[x]);
        }
    }
    return 0;
}
时间: 2024-08-27 09:49:02

HDU 5860 Death Sequence的相关文章

2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5860 题目大意:给你n个人排成一列编号,每次杀第一个人第i×k+1个人一直杀到没的杀.然后剩下的人重新编号从1-剩余的人数.按照上面的方式杀.问第几次杀的是谁. 分析 一轮过后和原来问题比只是人的编号发生变化,故可以转化为子问题求解,不妨设这n个人的编号是0~n-1,对于第i个人,如果i%k=0,那么这个人一定是第一轮出列的第i/k+1个人:如果i%k!=0,那么这个人下一轮的编号就是i

HDU 5860 Death Sequence (递推)

题意:n个人排成一行,从第一个人开始,每个k个人报数,报到数的人被杀死,剩下的人重新排成一行再报数.一共q个询问,每次询问第qi个死的人是谁. 析:是一个约瑟夫的变形,我们要考虑子问题的问题同样编号是0-n-1,如果在某一轮,第 i 个人如果能取模 k 为0,那么这一轮他就会被干掉,如果不是 那么下一轮他就是编号为 i-i/k-1,然后再处理每一轮多少个人被干掉,就OK了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&q

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ

hdu 4441 Queue Sequence(splay)

题目链接:hdu 4441 Queue Sequence 这题看了题解写的,题解传送门 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 #define ls l,m,rt<<1 4 #define rs m+1,r,rt<<1|1 5 using namespace std; 6 typedef long long ll; 7 8 const int N=1e6+7; 9 i

hdu 5297 Y sequence(容斥)

题目链接:hdu 5297 Y sequence 考虑62以内的指数,x为奇数个质数因子,就减掉,偶数个加上.计算x为指数的不满足数直接pow(n,1/x)即可. #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <algorithm> using namespace std; type

KMP算法的定义及KMP练手题 HDU 1711 Number Sequence (我的模板代码)

题意:就是要你来找出b数组在a数组中最先匹配的位置,如果没有则输出-1 思路:直接KMP算法(算法具体思想这位牛写的不错http://blog.csdn.net/v_july_v/article/details/7041827) AC代码: #include<cstdio> #include<cstring> #include<stdlib.h> #include<iostream> using namespace std; #define maxn 100

hdu 5306 Gorgeous Sequence(区间最值更新+求和)

题目链接:hdu 5306 Gorgeous Sequence 题意: 给你一个序列,有三种操作. 0 x y t:将[x,y]的数取min(a[i],t) 1 x y:求[x,y]的最大值 2 x y:求[x,y]的区间和 题解: 吉老师的课件题:传送门 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 #define ls l,m,rt<<1 4 #define rs m+1,r,rt

hdu 6025 Coprime Sequence (前后缀GCD)

题目链接:hdu 6025 Coprime Sequence 题意: 给你n个数,让你删掉一个数,使得剩下的数的gcd最大 题解: 先将这一列数的前缀后缀gcd预处理一下. 然后挨着for一下就行了 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 const int N=1e5+7; 6 int t,pre[N],suf[N],n,a[N]; 7 8

hdu 5014 Number Sequence(贪心)

题目链接:hdu 5014 Number Sequence 题目大意:给定n,表示有0~n这n+1个数组成的序列a,要求构造一个序列b,同样是由0~n组成,要求∑ai⊕bi尽量大. 解题思路:贪心构造,对于n来说,找到n对应二进制的取反对应的数x,那么从x~n之间的数即可两两对应,然后x-1即是一个子问题. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; con