2017.6.26 旅行 思考记录
来源:互联网 发布:英文缩写查询软件 编辑:程序博客网 时间:2024/06/05 00:32
这个题其实不算难,但复杂度一定要算清楚、、
如果没有宗教相同的限制,就是裸的树链剖分
但有了宗教相同的限制,我们可以想到对每个宗教开线段树、
直接建是肯定会炸的,所以需要动态开点、、
这样最复杂情况是 1*n+2*n/2+4*n/4+8*n/8... 所以就是n*logn的空间、、(惊人的小)
由于这个题它不是让你创算法,所以有个很好的修改方式——单点修改、
这样删除+增加就是2log的了,而且不用pushdown、
还有一个思路是每个节点开一个splay、、然后动态删除添加。。 它看似能做,是log^2n的,但这样修改时复杂度是不科学的、
一遍ac(主要是套路太死了)
码(变量名混乱)
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#include<vector>#define N 100005vector<int>v[N];int d[N],fu[N],sz[N],top[N],tot,hson[N],dui[N],pj[N],lpj[N],zj[N],lzj[N],he[N*40],n,m,cnt=N+1,max1[N*40],ll[N*40],rr[N*40],a,b,c,x,y,op,heans,maxans;char ch[55];void dfs1(int now,int fa,int shen){d[now]=shen;fu[now]=fa;sz[now]=1;for(int i=0;i<v[now].size();i++){int nd=v[now][i];if(nd==fa)continue;dfs1(nd,now,shen+1);sz[now]+=sz[nd];if(sz[nd]>sz[hson[now]])hson[now]=nd;}}void dfs2(int now,int tap){top[now]=tap;dui[now]=++tot;pj[tot]=lpj[now];zj[tot]=lzj[now];if(hson[now])dfs2(hson[now],tap);for(int i=0;i<v[now].size();i++){int nd=v[now][i];if(nd==fu[now]||nd==hson[now])continue;dfs2(nd,nd);}}void up(int o){he[o]=he[ll[o]]+he[rr[o]];max1[o]=max(max1[ll[o]],max1[rr[o]]);}void gai(int o,int l,int r){ if(a<=l&&b>=r){if(op==1){c=he[o];he[o]=0;max1[o]=0;}if(op==2){he[o]=c;max1[o]=c;}if(op==3)heans+=he[o];if(op==4)maxans=max(maxans,max1[o]);return;} // down(o,l,r); int mid=(l+r)>>1; if(a<=mid) { if(ll[o]==0)ll[o]=++cnt; gai(ll[o],l,mid); } if(b>mid) { if(rr[o]==0)rr[o]=++cnt; gai(rr[o],mid+1,r); } up(o);}void workgai(int x,int y){ a=dui[x];b=dui[x];if(op==1)//改信用 {gai(zj[a],1,tot); op=2; gai(y,1,tot); zj[a]=y; }else { c=y; gai(zj[a],1,tot); }}void workcha(int x,int y){int xyzj=zj[dui[x]];heans=0;maxans=0;while(top[x]!=top[y]){if(d[top[x]]>d[top[y]])swap(x,y);a=dui[top[y]];b=dui[y];gai(xyzj,1,tot);y=fu[top[y]]; }if(d[x]>d[y])swap(x,y);a=dui[x];b=dui[y];gai(xyzj,1,tot);}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d%d",&lpj[i],&lzj[i]);for(int i=1;i<n;i++){scanf("%d%d",&x,&y);v[x].push_back(y);v[y].push_back(x);}dfs1(1,1,1);dfs2(1,1);for(int i=1;i<=n;i++){ //cout<<dui[i]<<endl;;op=2;workgai(i,pj[dui[i]]);}for(int i=1;i<=m;i++){scanf("%s",ch);while(ch[0]!='C'&&ch[0]!='Q')scanf("%s",ch);scanf("%d%d",&x,&y);if(ch[0]=='C'){if(ch[1]=='C')op=1; else op=2;workgai(x,y);}if(ch[0]=='Q'){if(ch[1]=='S')op=3;else op=4;workcha(x,y);if(op==3)printf("%d\n",heans);elseprintf("%d\n",maxans);}}}
阅读全文
0 0
- 2017.6.26 旅行 思考记录
- 旅行记录
- 2017.6.6 数表 思考记录
- 2017.6.23 染色 思考记录
- 2017.8.26 力 思考记录
- 2017.6.3 完全平方数 思考记录
- 2017.6.15 数字表格 思考记录
- 2017.6.21 大都市meg 思考记录
- 2017.6.27 树上操作 思考记录
- 2017.6.28 文艺平衡树 思考记录
- 2017.4.26 组合数问题 思考记录
- 2017.9.26 块的计数 思考记录
- 2017.10.26 星际贸易 思考记录
- 记录一些思考
- 工作快两年思考记录
- 软件思考记录
- 思考记录--聊天机器人
- 20178.27 万径人踪灭 思考记录
- 小米手机android studio常见错误
- Jquery瀑布流布局
- mysql count多个表
- html常用知识
- Python刷csdn访问量
- 2017.6.26 旅行 思考记录
- [RK3288][Android6.0] RTC模块RX8010SJ驱动添加及改动
- WebAPI的学习简单分析
- 装饰模式设计原理
- 全局变量和局部变量在内存里的区别
- 学习体会-前后端传值低级问题
- 欢迎使用CSDN-markdown编辑器
- 旋转锁
- c++ 学习二维数组与指针