省选模拟赛20200229(by Ark) T3 买买买(动态点分治)

2024-02-20 09:40

本文主要是介绍省选模拟赛20200229(by Ark) T3 买买买(动态点分治),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

 

 

 

 

题解

٩(๑>◡<๑)۶人生第一道动态点分治٩(๑>◡<๑)۶

一开始我点分治都不怎么会,更别说动态点分治了

然后开始肝题解和std,肝了我两天,终于搞懂了

然后写了一上午+下午,调了一晚上,终于A掉了

如果不知道动态点分治,请看这里

其实这道题思路并不难想

点分树+线段树

只是修改边的时候会比较麻烦

考虑一条边改变权值会对哪些点产生影响,其实就是对dep值较大的端点的子树造成影响

但是在不同的点分中心下,这两个端点的dep值大小关系可能是不同的

所以边往上爬,边比较大小,修改线段树

 

我的代码中用的是dis值来比较的大小

这导致了一个我调了3个小时的错误:查询时会用到一个点到某个点分中心的dis,但是这个dis是会改变的,不能通过预处理保存下来,所以每次更新都需要边往上爬,边比较大小,边查询当前dis值,边修改线段树

这样就A了

代码:(其实还有一个错误,但是这个错误不影响程序的正确性,因为我们只需要保证该点自身不被查询到即可,所以在去除子树贡献是就不用那么严,可以少开一个fro数组)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define N 100005
#define LOG 18
#define LL long long
#define lc a[i].lch
#define rc a[i].rch
const LL INF=1ll<<60;
int fir[N],to[2*N],nxt[2*N],cnt;LL cd[2*N];
int siz[LOG][N],dfn[LOG][N],dc,dfa[N],dep[N];LL dis[LOG][N];
int tmpsiz[N],nrt,all;bool vis[N];
struct ansnode{LL mx;int pos;ansnode(){}ansnode(LL a,int b){mx=a;pos=b;}bool operator < (const ansnode &t)const{return mx<t.mx||(mx==t.mx&&pos>t.pos);}
}ans,tans;
struct node{int l,r,lch,rch;LL la;ansnode x;}a[N*LOG*3];
int T[N],tot;
LL val[N];//
map<pair<int,int>,LL> mp;inline LL gi()
{char c;LL num=0;while((c=getchar())<'0'||c>'9');while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}return num;
}
void adde(int a,int b,LL c)
{to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;cd[cnt]=c;to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt;cd[cnt]=c;
}
void findrt(int u,int ff)
{int mx=0;tmpsiz[u]=1;for(int v,p=fir[u];p;p=nxt[p]){if((v=to[p])!=ff&&!vis[v]){findrt(v,u);tmpsiz[u]+=tmpsiz[v];mx=max(mx,tmpsiz[v]);}}mx=max(mx,all-tmpsiz[u]);if(2*mx<=all)nrt=u;//mdzz wssb
}
int getrt(int u,int al)
{nrt=-1000000000;all=al;//-1e9:prevent the explosion of findrtfindrt(u,0);return nrt;
}
int tmpid[N];LL tmpval[N];
void pushdown(int i)
{if(a[i].la!=0&&a[i].l<a[i].r){a[lc].x.mx+=a[i].la;a[lc].la+=a[i].la;a[rc].x.mx+=a[i].la;a[rc].la+=a[i].la;a[i].la=0;}
}
void build(int &i,int l,int r)
{if(!i)i=++tot,a[i].l=l,a[i].r=r;if(l==r){a[i].x.mx=tmpval[l],a[i].x.pos=tmpid[l];return;}int mid=(l+r)>>1;build(lc,l,mid);build(rc,mid+1,r);a[i].x=max(a[lc].x,a[rc].x);
}
void insert(int i,int l,int r,LL k)
{if(a[i].l>r||l>a[i].r)return;pushdown(i);if(l<=a[i].l&&a[i].r<=r){a[i].x.mx+=k;a[i].la+=k;return;}insert(lc,l,r,k);insert(rc,l,r,k);a[i].x=max(a[lc].x,a[rc].x);
}
ansnode query(int i,int l,int r)
{if(a[i].l>r||a[i].r<l)return ansnode(-INF,1<<30);pushdown(i);if(l<=a[i].l&&a[i].r<=r)return a[i].x;return max(query(lc,l,r),query(rc,l,r));
}
void pre(int u,int ff,int d)
{dfn[d][u]=++dc;siz[d][u]=1;tmpid[dc]=u;tmpval[dc]=val[u]-dis[d][u];for(int v,p=fir[u];p;p=nxt[p]){if(!vis[v=to[p]]&&v!=ff){dis[d][v]=dis[d][u]+cd[p];pre(v,u,d);siz[d][u]+=siz[d][v];}}
}
void DFZ(int u,int d)
{vis[u]=1;dep[u]=d;dc=0;dis[d][u]=0;pre(u,0,d);if(siz[d][u]>1)build(T[u],2,siz[d][u]);for(int v,p=fir[u];p;p=nxt[p]){if(!vis[v=to[p]]){dfa[v=getrt(v,siz[d][v])]=u;DFZ(v,d+1);}}
}
int main()
{freopen("buy.in","r",stdin);freopen("buy.out","w",stdout);int n,Q,i,op,u,v,t;LL w,tmp;n=gi();Q=gi();for(i=1;i<=n;i++)val[i]=gi();for(i=1;i<n;i++){u=gi();v=gi();w=gi();adde(u,v,w);if(u>v)swap(u,v);mp[make_pair(u,v)]=w; }DFZ(getrt(1,n),1);int now=1;for(i=1;i<=Q;i++){op=gi();if(op==1){u=gi();w=gi();tmp=w-val[u];val[u]=w;for(t=dfa[u];t;t=dfa[t])insert(T[t],dfn[dep[t]][u],dfn[dep[t]][u],tmp);}else{u=gi();v=gi();w=gi();if(u>v)swap(u,v);tmp=w-mp[make_pair(u,v)];mp[make_pair(u,v)]=w;for(t=(dep[u]>dep[v]?v:u);t;t=dfa[t]){if(dis[dep[t]][u]<dis[dep[t]][v])swap(u,v);insert(T[t],dfn[dep[t]][u],dfn[dep[t]][u]+siz[dep[t]][u]-1,-tmp);}}ans=ansnode(-INF,1<<30);if(T[now])ans=query(T[now],2,siz[dep[now]][now]);//if(ans.pos!=(1<<30))printf("%d: %lld %d\n",i,ans.mx,ans.pos);for(t=dfa[now];t;t=dfa[t]){//LL del=dis[dep[t]][now];//wrong !!!!LL del=-(query(T[t],dfn[dep[t]][now],dfn[dep[t]][now]).mx-val[now]);//dis will change !!!!tans=max(ansnode(val[t],t),max(query(T[t],2,dfn[dep[t]][now]-1),query(T[t],dfn[dep[t]][now]+siz[dep[t]][now],siz[dep[t]][t])));tans.mx-=del;ans=max(ans,tans);////if(ans.pos!=(1<<30))printf("%d: %lld %d\n",i,ans.mx,ans.pos);}//printf("%d:### %lld %d\n",i,ans.mx,ans.pos);//printf("%d: ----------------------------\n",i);printf("%d\n",ans.pos);now=ans.pos;}
}

 

 

 

 

 

 

 

这篇关于省选模拟赛20200229(by Ark) T3 买买买(动态点分治)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/727803

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

【算法专场】模拟(下)

目录 前言 38. 外观数列 算法分析 算法思路 算法代码 1419. 数青蛙 算法分析 算法思路 算法代码  2671. 频率跟踪器 算法分析 算法思路 算法代码 前言 在前面我们已经讲解了什么是模拟算法,这篇主要是讲解在leetcode上遇到的一些模拟题目~ 38. 外观数列 算法分析 这道题其实就是要将连续且相同的字符替换成字符重复的次数+