smoj2011(神奇的线段树)
来源:互联网 发布:梦幻手游宝宝评分算法 编辑:程序博客网 时间:2024/06/07 05:51
这题依然是比赛是碰到的,当时以为自己会做,最后10分钟才知道要打暴力,结果暴力打错了(传说暴力有70)
后来问了很多大犇,用了一个上午才想清楚了。(也许我对线段树一无所知)
大概就是棵线段树
经过小小的计算,猜测出题人的阴谋,这题常数是10(实测100常数比暴力低分)。
对于线段树的每个结点,我们用s[10]表示该区间0~9分别的权值和。我们只要正确地维护这个信息,就可用10的常数获得答案。
本题的修改操作是把区间的s[y]+=s[x],s[x]清零,因为这题是线段树,所以一定懒惰,就设lz[x]=y,表示该区间的s[x]应加给s[y]。
然后考虑下放标记,我们用(父亲没标记)等价于(儿子信息正确)的方法。(即该区间有无标记与该区间信息正确性无关)
儿子的s就根据父亲的lz数组来维护,lz大概是这样维护的
这样大概就是对的了。
。。完了,我现在觉得这个做法就是错的,这个信息根本维护不了,就是想不明白这个lz能重叠但又有先后顺序的情况
2017.9.19
17:18
#include <iostream>#include <fstream>#include <algorithm>#include <cmath>#include <ctime>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define mmst(a, b) memset(a, b, sizeof(a))#define mmcp(a, b) memcpy(a, b, sizeof(b))typedef long long LL;const int N=100100;void read(int &hy){ char cc=getchar(); hy=0; while(cc<'0'||cc>'9') cc=getchar(); while(cc>='0'&&cc<='9') { hy=(hy<<3)+(hy<<1)+cc-'0'; cc=getchar(); }}int b[N];int n,q,lz[4*N][10],vis[10];LL ten[15],a[N][10],s[4*N][10],by[10];void up(int ro){ for(int i=0;i<=9;i++) s[ro][i]=s[ro*2][i]+s[ro*2+1][i];}void down(int ro,int l,int r){ if(l==r) return; int L=ro<<1,R=(ro<<1)|1; for(int i=0;i<=9;i++) vis[i]=lz[ro][lz[L][i]],by[i]=s[L][i]; for(int i=0;i<=9;i++) by[lz[ro][i]]+=s[L][i],by[i]-=s[L][i]; for(int i=0;i<=9;i++) lz[L][i]=vis[i],s[L][i]=by[i]; for(int i=0;i<=9;i++) vis[i]=lz[ro][lz[R][i]],by[i]=s[R][i]; for(int i=0;i<=9;i++) by[lz[ro][i]]+=s[R][i],by[i]-=s[R][i]; for(int i=0;i<=9;i++) lz[R][i]=vis[i],s[R][i]=by[i]; for(int i=0;i<=9;i++) lz[ro][i]=i;}LL get(int ro){ LL res=0ll; for(LL i=1;i<=9;i++) res+=s[ro][i]*i; return res;}void build(int ro,int l,int r){ for(int i=0;i<=9;i++) lz[ro][i]=i; if(l==r) { for(int i=0;i<=9;i++) s[ro][i]=a[l][i]; return; } int mid=(l+r)/2; build(ro*2,l,mid); build(ro*2+1,mid+1,r); up(ro);}void update(int ro,int l,int r,int zuo,int you,int x,int y){ down(ro,l,r); if(l>=zuo&&r<=you) { s[ro][y]+=s[ro][x]; s[ro][x]=0; lz[ro][x]=y; return; } int mid=(l+r)>>1; if(zuo<=mid) update(ro*2,l,mid,zuo,you,x,y); if(you>mid) update(ro*2+1,mid+1,r,zuo,you,x,y); up(ro);}LL query(int ro,int l,int r,int zuo,int you){ down(ro,l,r); if(l>you||r<zuo) return 0ll; if(l>=zuo&&r<=you) return get(ro); int mid=(l+r)>>1; return query(ro*2,l,mid,zuo,you)+query(ro*2+1,mid+1,r,zuo,you);}int main(){ cin>>n>>q; ten[0]=1ll; for(int i=1;i<=11;i++) ten[i]=ten[i-1]*10ll; for(int i=1;i<=n;i++) { read(b[i]); int tu=0; int bb=b[i]; while(b[i]) { a[i][b[i]%10]+=ten[tu]; tu++; b[i]/=10; } } build(1,1,n); while(q--) { int ops,l,r,x,y; read(ops); read(l); read(r); if(ops==2) printf("%lld\n",query(1,1,n,l,r)); else { read(x); read(y); if(x^y) update(1,1,n,l,r,x,y); } } return 0;}
阅读全文
1 0
- smoj2011(神奇的线段树)
- 神奇的线段树
- hdu 1540 神奇的线段树
- 【bzoj3165】[Heoi2013]Segment 神奇的线段树
- bzoj3244 NOI2013树的计数 神奇脑洞题+线段树
- HDU 5643 (神奇的打表 线段树)
- CF 452F Permution 神奇的线段树判断
- 【JZOJ5270】【GDOI2018模拟】神奇的矩阵(二维线段树)
- bzoj 3790: 神奇项链 (manacher+线段树优化DP)
- Bzoj3790:神奇项链:manacher+线段树+贪心
- JZOJ4417 【HNOI2016模拟4.1】神奇的字符串 线段树维护信息
- jzoj4417 【HNOI2016模拟4.1】神奇的字符串 (映射,权值线段树)
- 神奇的树
- 神奇的树
- 神奇的vfork()
- 神奇的vfork()
- 神奇的afxoleinit()
- 神奇的算法:B树
- YOLOv2训练自己的数据集(VOC格式)
- HDU 5934 Bomb(tarjan缩点)
- java使用xsd校验xml样例
- BZOJ1116 CLO [并查集]
- sed tips学习
- smoj2011(神奇的线段树)
- Oracle数据库学习整理day2
- Android Binder机制(超级详尽)
- Shader学习 之 ShaderLab语法: SubShader
- 基于SDL2.0和ffmpeg(2017,9,4版本)的简单视频播放器
- java (URL)生成二维码 代码以及遇到的问题
- 如何高效设计游戏——游戏平衡:RTS显性平衡与隐形平衡
- spring学习之配置文件
- 各大技术团队网站