zoukankan      html  css  js  c++  java
  • POJ 2886Who Gets the Most Candies?(线段树)

    POJ 2886

    题目大意是说有n个人围成一圈,游戏的起点是k,每个人持有一个数字(非编号)num,每次当前的人退出圈,下一个人是他左边的第num个(也就是说下一个退出的是k+num, k可以为负数,表示右边的第num个),这里的num的范围是1e9, 现在一直如果一个人是第i个推出的,那么他的得分就是i的约束的个数,球得分最高的那个人的编号

    这里有两个地方稍微不好处理:

    1: num  < 1e9 这里只需要模拟一下就可以了,如果当前在k,往右走num,还剩下rest个人,那么下一步应该往右走num % rest,同时先使用线段树计算出当前位置的左侧和右侧还有多少人,线段树里保存的是当前区间还剩下多少个人,线段树就可以查找出下一个需要推出的人的编号

    2:由于i的约数的个数是可以求出的,也就是说只需要在N内找到一个约束最大的数X,判断谁是第X个退出的就可以了。这里就用到了反素数的概念,设G[i]表示i的约数的个数,若对于任意的j,j<i有G[i] > G[j],那么i就是i反素数,这道题就转化为了球N以内的最大的反素数,设Max[i]为i以内的最大的反素数是Max[i]。在计算反素数时,设D[i]为i的约数的个数,由于对于i的一个素因子a,i除尽a后得到的a的幂是b,有D[i] = D[i/a] * (b+1) / b,而在计算D[i]时,D[i/a]已经被计算出,所以按照DP的思路,总体的复杂度就是NlonN(logN为求b时的复杂度)

      1 #include <map>
      2 #include <set>
      3 #include <stack>
      4 #include <queue>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <vector>
      8 #include <cstdio>
      9 #include <cctype>
     10 #include <cstring>
     11 #include <cstdlib>
     12 #include <iostream>
     13 #include <algorithm>
     14 using namespace std;
     15 #define INF 1e9
     16 #define inf (-((LL)1<<40))
     17 #define lson k<<1, L, mid
     18 #define rson k<<1|1, mid+1, R
     19 #define mem0(a) memset(a,0,sizeof(a))
     20 #define mem1(a) memset(a,-1,sizeof(a))
     21 #define mem(a, b) memset(a, b, sizeof(a))
     22 #define FOPENIN(IN) freopen(IN, "r", stdin)
     23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
     24 template<class T> T CMP_MIN(T a, T b) { return a < b; }
     25 template<class T> T CMP_MAX(T a, T b) { return a > b; }
     26 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
     27 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
     28 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
     29 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
     30 
     31 typedef __int64 LL;
     32 //typedef long long LL;
     33 const int MAXN = 500005;
     34 const int MAXM = 100005;
     35 const double eps = 1e-10;
     36 const LL MOD = 1000000007;
     37 
     38 char name[MAXN][20];
     39 int N, K,cnt, l, r, curPos;
     40 int num[MAXN], tree[MAXN<<2], no[MAXN];
     41 
     42 void buildTree(int k, int L, int R)
     43 {
     44     if(L == R) { tree[k] = 1; return ; }
     45 
     46     int mid = (L + R) >> 1;
     47 
     48     buildTree(lson);  buildTree(rson);
     49 
     50     tree[k] = tree[k<<1] + tree[k<<1|1];
     51 }
     52 
     53 void update(int k, int L, int R, int x)
     54 {
     55     if(L == R) { tree[k] = 0; no[L] = cnt; curPos = L; return ;}
     56 
     57     int mid = (L + R) >> 1;
     58 
     59     if(x <= tree[k<<1]) update(lson, x);
     60 
     61     else update(rson, x-tree[k<<1]);
     62 
     63     tree[k] = tree[k<<1] + tree[k<<1|1];
     64 }
     65 
     66 int query(int k, int L, int R)
     67 {
     68     if(R < l || r < L) return 0;
     69 
     70     if(l<=L && R<=r) return tree[k];
     71 
     72     int mid = (L+R) >> 1;
     73 
     74     return query(lson) + query(rson);
     75 }
     76 
     77 void getNo()
     78 {
     79     cnt = 1; int pos = K;
     80     for(int j=0;j<N-1;j++)
     81     {
     82         update(1, 1, N, pos);
     83         l = 1; r = curPos; int leftNum = query(1, 1, N);
     84         l = curPos; r = N; int rightNum = query(1, 1, N);
     85         int dis = abs(num[curPos]) % (N - cnt);
     86         if(dis == 0) dis = N - cnt;
     87         if(num[curPos] > 0 && rightNum >= dis) pos = leftNum + dis;
     88         else if(num[curPos] >  0 && rightNum <  dis) pos = dis - rightNum;
     89         else if(num[curPos] <  0 && leftNum  >= dis) pos = leftNum - dis + 1;
     90         else if(num[curPos] <  0 && leftNum  <  dis) pos = 2*leftNum + rightNum - dis + 1;
     91         cnt ++;
     92     }
     93     for(int i=1;i<=N;i++)if(!no[i]) no[i] = N;
     94 }
     95 
     96 int isp[MAXN], yue[MAXN], D[MAXN], Max[MAXN];
     97 void init()
     98 {
     99     mem1(isp);yue[1] = 1;
    100     for(int i=2;i<MAXN;i++) if(isp[i])
    101     {
    102         for(int j=2*i;j<MAXN;j+=i)
    103         {
    104             isp[j] = 0;
    105             yue[j] = i;
    106         }
    107     }
    108     D[1] = Max[1] = 1;
    109     for(int i=2;i<MAXN;i++)
    110     {
    111         if(isp[i]) D[i] = 2;
    112         else
    113         {
    114             int last = i / yue[i];
    115             int b = 0, n = i;
    116             while(n % yue[i] == 0) b ++, n /= yue[i];
    117             D[i] = D[last] * (b+1) / b;
    118         }
    119         if(D[i] > D[Max[i-1]]) Max[i] = i;
    120         else Max[i] = Max[i-1];
    121     }
    122 }
    123 
    124 int main()
    125 {
    126     //FOPENIN("in.txt");
    127     init();
    128     while(~scanf("%d %d%*c", &N, &K))
    129     {
    130         mem0(tree); mem0(no);
    131         buildTree(1, 1, N);
    132         for(int i=1;i<=N;i++)
    133             scanf("%s %d", name[i], &num[i]);
    134         getNo();
    135         for(int i=1;i<=N;i++) if(no[i] == Max[N])
    136             printf("%s %d
    ", name[i], D[Max[N]]);
    137     }
    138     return 0;
    139 }
  • 相关阅读:
    Oracle 11G单机 无网络环境静默安装
    Centos 7 编译安装llvm 8.0.0
    linux下测试读写
    Linux 初始化 init 系统(1):sysvinit
    自动挂载文件/etc/fstab功能详解
    虚拟机安装LINUX网络配置注意的问题
    rhel7报错整理
    16/4/4二代支付硬盘故障处理
    RedHat Enterprise Linux 7关闭防火墙方法
    Linux命令之awk数组使用范例
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/3884816.html
Copyright © 2011-2022 走看看