1521. War Games 2(线段树解约瑟夫)

1521

根据区间和 来确定第k个数在哪

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<stdlib.h>
 6 using namespace std;
 7 #define N 100010
 8 int s[N<<2],tt;
 9 void up(int w)
10 {
11     s[w] = s[w<<1]+s[w<<1|1];
12 }
13 void build(int l,int r,int w)
14 {
15     if(l==r)
16     {
17         s[w] = 1;
18         return ;
19     }
20     int m = (l+r)>>1;
21     build(l,m,w<<1);
22     build(m+1,r,w<<1|1);
23     up(w);
24 }
25 void update(int k,int l,int r,int w)
26 {
27     if(l==r)
28     {
29         s[w] = 0;
30         tt = l;
31         return ;
32     }
33     int m = (l+r)>>1;
34     if(k<=s[w<<1])
35     update(k,l,m,w<<1);
36     else
37     update(k-s[w<<1],m+1,r,w<<1|1);
38     up(w);
39 }
40 int getsum(int a,int b,int l,int r,int w)
41 {
42     if(a<=l&&b>=r)
43     {
44         return s[w];
45     }
46     int m = (l+r)>>1,re=0;
47     if(a<=m)
48     re+=getsum(a,b,l,m,w<<1);
49     if(b>m)
50     re+=getsum(a,b,m+1,r,w<<1|1);
51     return re;
52 }
53 int main()
54 {
55     int k,n,o=0,ss=0;
56     scanf("%d%d",&n,&k);
57     build(1,n,1);
58     int m = n;
59     while(n)
60     {
61         if(tt)
62         {
63             ss = getsum(1,tt,1,m,1);
64             o = (k+ss)%s[1];
65         }
66         else
67         o = k%s[1];
68         if(o==0)
69         o=s[1];
70         update(o,1,m,1);
71         n--;
72         if(n)
73         printf("%d ",tt);
74         else
75         printf("%d\n",tt);
76     }
77     return 0;
78 }
View Code

 

posted @ 2013-09-27 18:09  _雨  阅读(355)  评论(0编辑  收藏  举报