洛谷3987之我的解法
来源:互联网 发布:wifi定位技术算法 编辑:程序博客网 时间:2024/05/22 10:29
首先正如官方题解所述“瓶颈在于如何找出所有该被/的数而不在于如何维护”。
考虑离线来完成这一步。对于每个操作set<int> e[A+5];
,并e[x].insert(id)
)然后在
然后对于一个set<int>
的*begin()
取出来,以询问的先后顺序为关键字建立一个堆。然后模拟
如果直接用普通的堆,那么是尽管出题人扬言有空了要卡掉这种算法。
注意到pop的次数远大于push的次数,考虑快速(
然而这是不存在的,因为基于比较的排序是
如果不考虑快速建立,那么平衡树是不错的选择,对于每个节点维护指向前驱后继的指针即可。
其实平衡树在原序列有序的情况下也能sort
会多log。
对于这一点,把所有元素离线下来(离线套离线,离线算法的子算法仍要离线,有趣),然后基数排序即可。
就这样,基数排序+平衡树+set
+vector
+树状数组总算达到了std的复杂度,然而已经不想写了。
据说原始平衡树版本的std有4到5K,可能不比我这种算法好多少?
可是分块版本的std又快又短。
我这种算法也只能是娱乐大众了。
下面是我原始的
#pr\agma GCC optimize("O2")#include<vector>#include<set>#include<cstdio>#include<cctype>#include<queue>using namespace std;typedef long long ll;inline void read(int&x){ char c=getchar(); for(;!isdigit(c);c=getchar()); for(x=0;isdigit(c);c=getchar())x=x*10+c-48;}const int N=100005,A=500000;vector<int> d[A+5],b[N];vector<pair<int,int> > op[N];set<int> e[A+5];set<int>::iterator it;int n,i,m,l[N],r[N],x[N],o[N],a[N],y,j,k,z;ll s[N];inline void add(int i,int x){for(;i<=n;i+=i&-i)s[i]+=x;}inline ll query(int i){register ll ans=0;for(;i;i-=i&-i)ans+=s[i];return ans;}struct node{ int id; set<int>::iterator it; bool operator<(const node&rhs)const{ return *it>*rhs.it; }}xx;struct pq{ static const int N=450; int l[N],r[N],rt,d[N],q[N],t,w,t2; node v[N]; int merge(int x,int y){ if(!x || !y)return x|y; if(v[x]<v[y])t2=x,x=y,y=t2; r[x]=merge(r[x],y); if(d[r[x]]>d[l[x]])t2=l[x],l[x]=r[x],r[x]=t2; d[x]=d[r[x]]+1; return x; } inline void ini(){t=1,w=0;} inline void pb(const node&x){ v[++w]=x;l[w]=r[w]=0;d[w]=1;q[w]=w; } inline void ini2(){ for(;t<w;t+=2)q[++w]=merge(q[t],q[t+1]);rt=q[w]; } const node& top(){return v[rt];} inline void pop(){rt=merge(l[rt],r[rt]);} inline bool empty(){return !rt;} inline bool push(const node&x){ v[++w]=x;l[w]=r[w]=0;d[w]=1;rt=merge(rt,w); }}qq;int main(){ //freopen("1.txt","r",stdin);freopen("2.txt","w",stdout); read(n),read(m); for(i=1;i<=n;++i)read(a[i]),add(i,a[i]); for(i=2;i<=A;++i) for(j=i;j<=A;j+=i)d[j].push_back(i); for(i=1;i<=m;++i){ read(o[i]);read(l[i]);read(r[i]); if(o[i]==1)read(x[i]),b[l[i]].push_back(i),b[r[i]+1].push_back(i); } for(i=1;i<=n;++i){ for(j=0;j<(int)b[i].size();++j){ y=b[i][j]; if(i==l[y])e[x[y]].insert(y); else e[x[y]].erase(y); } qq.ini(); for(j=0;j<(int)d[a[i]].size();++j){ y=d[a[i]][j]; if(!e[y].empty())qq.pb((node){y,e[y].begin()}); } qq.ini2(); for(y=a[i];!qq.empty() && y>1;){ xx=qq.top();qq.pop(); it=xx.it;j=*it; if(y%x[j]==0){ y/=x[j]; op[j].push_back(make_pair(i,y)); if(++it!=e[xx.id].end())qq.push((node){xx.id,it}); } } } for(i=1;i<=m;++i){ for(j=0;j<(int)op[i].size();++j){ y=op[i][j].first,z=op[i][j].second; add(y,z-a[y]);a[y]=z; } if(o[i]==2)printf("%lld\n",query(r[i])-query(l[i]-1)); } return 0;}
- 洛谷3987之我的解法
- 我的螺旋矩阵解法!
- 编程作业-我的解法
- 迷宫解法之栈/队列的解法
- 我的google jam 入围赛之wordPath的一个解法
- 2012年校园招聘华为一道面试题---之我的解法
- 中兴通讯2012校园招聘一道面试题---之我的解法
- 2012年华为校园招聘电子科大面试题---之我的解法
- 一道面试题,我的解法
- 阿里实习生电面题 我的解法
- fcgx_accept_r 返回-88 我的解法
- Divide Two Integers我的解法
- 463. Island Perimeter我的解法
- LeetCode500. Keyboard Row我的C++解法
- leetcode--Hamming Distance _我的解法
- CSAW2016之PWN题目tutorial的解法
- google的一道面试题!(附我的解法)
- 关于google的JAVA面试题我的解法
- effective java 34条 通过接口引用对象
- sigmoid函数matlab绘制曲线
- NYACM_006
- scala学习笔记-高阶函数
- HDU-OJ2041解题心得
- 洛谷3987之我的解法
- linux下mysql主从同步
- nsq简单安装以及测试
- 最短路径—Dijkstra算法和Floyd算法
- 接口优于反射
- java 时间转换错误 月份始终转换成1月
- OpenCV+Python车牌字符分割和识别入门
- hibernate_day04_17_hibernate批量抓取
- python 判断list是否为空