HDU 4630 No Pain No Game(树状数组)

题目链接

看的别人的题解,离线之后,按r排序,枚举1-n,利用pre[j],存上次j的倍数出现的位置,树状数组里统计的当前位置到最后的最大值,树状数组是求区间最值其实应该很麻烦的,但是此题用法只是求到最后的最大值,插入的时候,往前更新就好了,类似求和。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 int num[50100];
 6 int p[50100];
 7 int n;
 8 struct node
 9 {
10     int l,r,id;
11 } que[50001];
12 bool cmp(node a,node b)
13 {
14     return a.r < b.r;
15 }
16 bool cmp1(node a,node b)
17 {
18     return a.id < b.id;
19 }
20 int pre[50101];
21 int ans[50101];
22 int lowbit(int t)
23 {
24     return t&(-t);
25 }
26 void insert(int t,int d)
27 {
28     while(t)
29     {
30         p[t] = max(p[t],d);
31         t -= lowbit(t);
32     }
33 }
34 int getmax(int t)
35 {
36     int maxz = 0;
37     while(t <= n)
38     {
39         maxz = max(maxz,p[t]);
40         t += lowbit(t);
41     }
42     return maxz;
43 }
44 int main()
45 {
46     int i,j,t,m,tnum;
47     scanf("%d",&t);
48     while(t--)
49     {
50         memset(p,0,sizeof(p));
51         memset(pre,0,sizeof(pre));
52         scanf("%d",&n);
53         for(i = 1; i <= n; i ++)
54             scanf("%d",&num[i]);
55         scanf("%d",&m);
56         for(i = 0; i < m; i ++)
57         {
58             scanf("%d%d",&que[i].l,&que[i].r);
59             que[i].id = i;
60         }
61         sort(que,que+m,cmp);
62         tnum = 0;
63         for(i = 1; i <= n; i ++)
64         {
65             if(tnum == m) break;
66             for(j = 1; j*j <= num[i]; j ++)
67             {
68                 if(num[i]%j == 0)
69                 {
70                     if(pre[j] != 0)
71                         insert(pre[j],j);
72                     pre[j] = i;
73                     if (j * j== num[i]) continue ;
74                     if(pre[num[i]/j] != 0)
75                         insert(pre[num[i]/j],num[i]/j);
76                     pre[num[i]/j] = i;
77                 }
78             }
79             while(tnum < m&&que[tnum].r == i)
80             {
81                 ans[que[tnum].id] = getmax(que[tnum].l);
82                 tnum ++;
83             }
84         }
85         sort(que,que+m,cmp1);
86         for(i = 0;i < m;i ++)
87         {
88             if(que[i].l == que[i].r)
89             printf("0\n");
90             else
91             printf("%d\n",ans[i]);
92         }
93     }
94     return 0;
95 }

 

转载于:https://www.cnblogs.com/naix-x/p/3229330.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值