hihoCoder - 1116 - 计算 (线段树区间合并)
来源:互联网 发布:java发送邮件的代码 编辑:程序博客网 时间:2024/04/30 14:00
线段树区间合并的题目套路就是每一段维护
1.当前段的答案data[k],
2.当前段所有前缀Left[k]
3.当前段所有后缀Right[k]
合并时由当前段的左右子节点的data转移当前段,
还有左子节点的后缀与右子节点的前缀合并形成的区间对当前段的贡献。
然后维护当前段Left,Right就ok了。
现在很少看见用vect或者map维护每一段前后缀的了(我会说是跑的太慢了吗)。
一般都会用组合数学优化一下或者二进制优化。
这里也不例外,当前段的每一个前后缀都是乘积Left,Right只是这些前后缀的和,
1.当前段的答案data[k],
2.当前段所有前缀Left[k]
3.当前段所有后缀Right[k]
合并时由当前段的左右子节点的data转移当前段,
还有左子节点的后缀与右子节点的前缀合并形成的区间对当前段的贡献。
然后维护当前段Left,Right就ok了。
现在很少看见用vect或者map维护每一段前后缀的了(我会说是跑的太慢了吗)。
一般都会用组合数学优化一下或者二进制优化。
这里也不例外,当前段的每一个前后缀都是乘积Left,Right只是这些前后缀的和,
合并原理类似多项式乘法,(和的乘积等于两个多项式的乘积)
#include <iostream>#include <cstdio>#include <cstdlib>#include <vector>#include <map>#define mid (l+r>>1)#define lson k<<1,l,mid#define rson k<<1|1,mid+1,rusing namespace std;const int mod=10007;const int maxn=1e5+7;int data[maxn*4];int Len[maxn*4];int Left[maxn*4],Right[maxn*4];void update(int k,int l,int r,int p,int v){ if(p<l||r<p)return ; if(l==r){ Len[k]=Left[k]=Right[k]=data[k]=v%mod; return ; } if(p<=mid) update(lson,p,v); else update(rson,p,v); data[k]=(data[k<<1]+data[k<<1|1])%mod; data[k]=(data[k]+(Right[k<<1]*Left[k<<1|1])%mod)%mod; Left[k]=((Len[k<<1]*Left[k<<1|1])%mod+Left[k<<1])%mod; Right[k]=((Len[k<<1|1]*Right[k<<1])%mod+Right[k<<1|1])%mod; Len[k]=(Len[k<<1]*Len[k<<1|1])%mod;}int main(){ int n,q; while(~scanf("%d%d",&n,&q)){ int siz=min(n*8,maxn*4); fill(data,data+siz,0); fill(Left,Left+siz,0); fill(Right,Right+siz,0); for(int i=0;i<q;i++){ int p,v; scanf("%d%d",&p,&v); update(1,1,n,p,v); printf("%d\n",data[1]%mod); } } return 0;}
放上我SB的map。
#include <iostream>#include <cstdio>#include <cstdlib>#include <vector>#include <map>#define mid (l+r>>1)#define lson k<<1,l,mid#define rson k<<1|1,mid+1,rusing namespace std;const int mod=10007;const int maxn=1e5+7;int data[maxn*4];int Len[maxn*4];map<int,int > Left[maxn*4],Right[maxn*4];map<int,int>::iterator it,ip;void update(int k,int l,int r,int p,int v){//printf("k==%d l==%d r==%d\n",k,l,r); if(p<l||r<p)return ; if(l==r){ data[k]=v%mod; Left[k].clear(); Right[k].clear(); Left[k][(v%mod)]=1; Right[k][(v%mod)]=1; Len[k]=v%mod;//printf("data[%d]==%d \n",k,data[k]); return ; } if(p<=mid) update(lson,p,v); else update(rson,p,v); data[k]=(data[k<<1]+data[k<<1|1])%mod; for(it=Right[k<<1].begin();it!=Right[k<<1].end();it++){ for(ip=Left[k<<1|1].begin();ip!=Left[k<<1|1].end();ip++){ int t1=it->first%mod,t2=it->second%mod,t3=ip->first%mod,t4=ip->second%mod; //printf("k== %d t1=%d t2=%d t3=%d t4=%d\n",k,t1,t2,t3,t4); int t5=((((t1*t3)%mod)*t2)%mod)*t4%mod; data[k]=(data[k]+t5)%mod; } } //printf("haha\n"); Left[k].clear(); for(it=Left[k<<1|1].begin();it!=Left[k<<1|1].end();it++){ int t1=it->first%mod,t2=it->second%mod; Left[k][(t1*Len[k<<1])%mod]=(Left[k][(t1*Len[k<<1])%mod]+t2)%mod; } for(it=Left[k<<1].begin();it!=Left[k<<1].end();it++) Left[k][(it->first)%mod]=(Left[k][(it->first)%mod]+it->second)%mod;//printf("haha2\n"); /////// Right[k].clear();//printf("%d %d\n",Right[k<<1].size(),Right[k<<1|1].size()); for(it=Right[k<<1].begin();it!=Right[k<<1].end();it++){ int t1=it->first%mod,t2=it->second%mod;//printf("k<<1==%d %d %d \n",k<<1,t1,t2); Right[k][(t1*Len[k<<1|1])%mod]=(Right[k][(t1*Len[k<<1|1])%mod]+t2)%mod; //Right[k].push_back((Right[k<<1][i]*Right[k<<1|1][0])%mod);//printf("Right[k]==%d*%d \n",Right[k<<1][i],Right[k<<1|1][0]); } for(it=Right[k<<1|1].begin();it!=Right[k<<1|1].end();it++) Right[k][it->first%mod]=(Right[k][it->first%mod]+it->second%mod)%mod;//printf("haha3\n"); Len[k]=(Len[k<<1]*Len[k<<1|1])%mod; //printf("data[%d]==%d Len %d %d %d\n",k,data[k],Len[k],Len[k<<1],Len[k<<1|1]);}void debug(int k,int l,int r){ printf("debug k==%d data=%d Len=%d Left=%d Right=%d\n",k,data[k],Len[k],Left[k].size(),Right[k].size()); for(it=Left[k].begin();it!=Left[k].end();it++)printf("Left k==%d %d %d\n",k,it->first,it->second); for(it=Right[k].begin();it!=Right[k].end();it++)printf("Right k==%d %d %d\n",k,it->first,it->second); if(l==r)return ; debug(lson); debug(rson);}int main(){ int n,q; while(~scanf("%d%d",&n,&q)){ int siz=min(n*8,maxn*4); fill(data,data+siz,0); for(int i=0;i<siz;i++){ Left[i].clear();//Left[i][0]=1; Right[i].clear();//Right[i][0]=1; }//debug(1,1,n); for(int i=0;i<q;i++){ int p,v; scanf("%d%d",&p,&v); update(1,1,n,p,v); //printf("-----------\n");debug(1,1,n);printf("--------------\n"); printf("%d\n",data[1]%mod); } } return 0;}
0 0
- hihoCoder 1116 计算 线段树 + 区间合并
- hihoCoder#1116-计算[线段树+合并区间]
- hihoCoder - 1116 - 计算 (线段树区间合并)
- hihocoder-1116 : 计算 (线段树区间合并)
- hihocoder 1116 : 计算(线段树 区间合并)
- hihoCoder - 1116 - 计算 (线段树)
- hihocoder#1116 : 计算(线段树)
- 线段树 (区间合并)
- HihoCoder 1078(线段树,区间覆盖 询问区间和)
- 线段树 区间合并
- 线段树 区间合并
- 线段树 区间合并
- 线段树 区间合并
- 线段树-区间合并
- poj3667 线段树(区间合并)
- hdu3308(线段树,区间合并)
- poj3667(线段树,区间合并)
- poj3667 Hotel (线段树区间合并)
- MYSQL的学习笔记------MYSQL的基本语法
- Android面试知识点-java篇
- python之正则表达式匹配全部findall()方法
- 第一讲项目2-长方形面积
- 前段技术杂记--Javascript
- hihoCoder - 1116 - 计算 (线段树区间合并)
- MYSQL的学习笔记-----MYSQL的约束
- Mysqlbackup 备份详解(mysql官方备份工具)
- 边框属性Border的终极研究
- java获取当前时间、当前零点零分零秒、昨天这一时间
- Linux中JDK的安装和配置方法
- Hibernate中反射优势
- 教你在“运行”中打开常用系统设置(转)
- 《数据结构导论之二叉树》