URAL 1846 线段树 最大公约数
2012-03-28 21:29
169 查看
链接:http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=23701
题意:求n个点的最大公约数,有两种操作,增加一个数,删去一个数,删去的数肯定是已经存在的
离线处理,先要离散化
然后找到每个数相应的位置插入或删除,简单的单点更新
gcd(a,b,c,d)=gcd(gcd(a,b),gcd(c,d));
View Code
题意:求n个点的最大公约数,有两种操作,增加一个数,删去一个数,删去的数肯定是已经存在的
离线处理,先要离散化
然后找到每个数相应的位置插入或删除,简单的单点更新
gcd(a,b,c,d)=gcd(gcd(a,b),gcd(c,d));
View Code
#include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn = 111111; int sum[maxn<<2]; inline int gcd(int a,int b) { return a==0?b:gcd(b%a,a); } void update(int p,int v,int l,int r,int rt){ if(l==r){ sum[rt]=v; return ; } int m=(l+r)>>1; if(p<=m) update(p,v,lson); else update(p,v,rson); sum[rt]=gcd(sum[rt<<1],sum[rt<<1|1]); } int flag[100100], vis[100100], num[100010]; int main(){ int n,i,j; char op[5]; while(scanf("%d",&n)!=EOF){ vector<int> val; memset(sum,0,sizeof(sum)); for(i=1;i<=n;i++){ scanf("%s%d",op,&num[i]); val.push_back(num[i]); flag[i]=(op[0]=='+'); } sort(val.begin(),val.end()); int tot=unique(val.begin(),val.end())-val.begin(); int cnt=0;memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++){ int pos=lower_bound(val.begin(),val.begin()+tot,num[i])-val.begin()+1; if(flag[i]){ cnt++; vis[pos]++;//printf("pos=%d\n",pos); if(vis[pos]==1) update(pos,val[pos-1],1,tot,1);//val[]的下标从0开始 } else{ cnt--; vis[pos]--; if(vis[pos]==0) update(pos,0,1,tot,1); } if(cnt==0) printf("1\n"); else printf("%d\n",sum[1]); } } return 0; }
相关文章推荐
- ural 1846. GCD 2010(线段树)
- 线段树求和,最大公约数
- 求最大公约数
- C语言笔记最大公约数和最小公倍数
- 第12周项目 3.3 递归 两个数的最大公约数
- 最大公约数
- hdu 1754 线段树区间最大值 单点更新
- 最大公约数最小公倍数
- 最大公约数
- C#实现用欧几里德算法、连续整数检测算法、公因数算法求两个非负整数的最大公约数
- 最大公约数和最小公倍数
- BZOJ 3218 a + b Problem 最大流 + 可持久化线段树
- hdu 2795 Billboard - 线段树 -区间最大值
- BZOJ 3218|UOJ 77|A + B Problem|最大流|可持久化线段树
- 最大公约数与最大公倍数
- 递归:最小公倍数和最大公约数求解
- poj 1091 跳蚤(最大公约数原理+容斥原理)
- caioj1099 线段树(区间修改+求区间最大值
- 最大公约数与最小公倍数问题
- 辗转相除法求两个数的最大公约数