hdu 4630 树状数组 ****

题意:Given you a sequence of number a1, a2, ..., an.They are also a permutation of 1...n.
You need to answer some queries,each with the following format:

If we chose two number a,b (shouldn‘t be the same) from interval [l,
r],what is the maximum gcd(a, b)? If there‘s no way to choose two
distinct number(l=r) then the answer is zero.

思路:这题的处理方式和hdu4358有点像。我们用一个pre[x]表示约数x的倍数上次出现的位置,将查询按区间的右节点升序排序。num[i]的约 数为j,如果pre[j]为0,就将pre[j]置为i;否则就update(pre[j],j),表示的意思是约数j肯定不是第一次出现,将 pre[j]以前的区间更新最大约数。如果查询区间的右边界在i处,那么左边界在pre[j]以前就肯定就能取到j。因为num[pre[j]]和 num[i]有一个公共约数j,且pre[j]和i被该查询区间所覆盖。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define Maxn 50010
 6 #define lowbit(x) (x&(-x))
 7 using namespace std;
 8 int C[Maxn],n,num[Maxn],pre[Maxn],q,ans[Maxn];
 9 struct QT{
10     int l,r,i;
11     int operator <(const QT &temp) const
12     {
13         return r<temp.r;
14     }
15 }qt[Maxn];
16 int Sum(int pos)//往后找
17 {
18     int sum=0;
19     while(pos<=n)
20     {
21         sum=max(sum,C[pos]);
22         pos+=lowbit(pos);
23     }
24     return sum;
25 }
26 void update(int pos,int val)//更新pos以前的位置
27 {
28     while(pos)
29     {
30         C[pos]=max(C[pos],val);
31         pos-=lowbit(pos);
32     }
33 }
34 int main()
35 {
36     int t,i,j;
37     scanf("%d",&t);
38     while(t--)
39     {
40         memset(C,0,sizeof(C));
41         memset(pre,0,sizeof(pre));
42         scanf("%d",&n);
43         for(i=1;i<=n;i++)
44             scanf("%d",num+i);
45         scanf("%d",&q);
46         for(i=1;i<=q;i++)
47         {
48             scanf("%d%d",&qt[i].l,&qt[i].r);
49             qt[i].i=i;
50         }
51         sort(qt+1,qt+1+q);
52         int r=1;
53         for(i=1;i<=n;i++)
54         {
55             if(r>q) break;
56             for(j=1;j*j<=num[i];j++)
57             {
58                 if(num[i]%j) continue;
59                 if(pre[j]) update(pre[j],j);
60                 pre[j]=i;
61                 if(j*j==num[i]) break;
62                 int k=num[i]/j;
63                 if(pre[k]) update(pre[k],k);
64                 pre[k]=i;
65             }
66             while(qt[r].r==i&&r<=q)
67             {
68                 ans[qt[r].i]=Sum(qt[r].l);
69                 r++;
70             }
71         }
72         for(i=1;i<=q;i++)
73             printf("%d\n",ans[i]);
74     }
75     return 0;
76 }
时间: 2024-11-09 20:55:50

hdu 4630 树状数组 ****的相关文章

hdu 4630 树状数组+离线操作+GCD

http://acm.hdu.edu.cn/showproblem.php?pid=4630 重新认识了树状数组. 首先要记住那个树形的图,然后+或-lowbit(i)是自己根据具体问题设定的,不要死于+或者-, 树状数组的特点: 1.+lowbit(i)可以到达包含结点i的上一层父节点    所以用于值的更改 2.-lowbit(i)可以到达不包含i所代表区间的上一层父节点  所以用于值的求和---每个不相交的段加起来 3.C[i]的含义也是根据具体问题去做设定的,但是c[i]覆盖了a[i-2

hdu 3333 树状数组+离线处理

http://acm.hdu.edu.cn/showproblem.php?pid=3333 不错的题,想了很久不知道怎么处理,而且答案没看懂,然后找个例子模拟下别人的代码马上懂了---以后看不懂的话就拿个例子模拟下别人的代码 举个例子:1 3 3 5 3 5 查询 a, 2 4 b, 2 5 最初是这么想的:对于a查询,倘若把第二个数第三个数变成1个3,那么到b查询,又出现了两个3,再做处理似乎还是O(n),而且如果先出现2,5查询,后出现2,4查询,那么还需要把删除的数补回来.....o(╯

Hdu 3887树状数组+模拟栈

题目链接 Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1757    Accepted Submission(s): 582 Problem Description You are given a tree, it’s root is p, and the node is numbered fr

HDU 1754 树状数组 解法

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

HDU 1166(树状数组)

用树状数组把HDU1166再写了一次  感觉树状数组简洁 1 #include <cstdio> 2 #include <iostream> 3 #include <string.h> 4 using namespace std; 5 int c[50002],lv[50002],n; 6 int lowbit(int x){return x&(-x);} 7 int sum(int b){ 8 int sum=0; 9 while(b>0){ 10 su

hdu 4368 树状数组 离线维护

http://acm.hdu.edu.cn/showproblem.php?pid=4638 Problem Description There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is i and i-1 are friends, Whose ID is i and i+1 are friends. These n men stand in line. Now we select an interv

HDU 1394 树状数组(逆序数)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10100    Accepted Submission(s): 6192 Problem Description The inversion number of a given number sequence a1, a2, ..., an

hdu 4970 树状数组区间更新 思维题

http://acm.hdu.edu.cn/showproblem.php?pid=4970 好像还没有用树状数组写过区间更新,但是树状数组的确比线段树快很多,不知道跟ZKW线段树比效率怎么样: 先贴个模板: #include <cstdio> const int MAXN = 1024; int B[MAXN], C[MAXN]; #define LOWBIT(x) ((x)&(-(x))) void bit_update(int *a, int p, int d) { for (

hdu 2492(树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2492 Ping pong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4011    Accepted Submission(s): 1482 Problem Description N(3<=N<=20000) ping pong