HDU 6039 Gear Up(2017 Multi-University Training Contest 1)
題目連結:Here
題意:給你一些齒輪以及齒輪之間的關係,然後每次有兩種操作:1.把第x個齒輪的半徑更改為y;2.給第x個齒輪一個大小為y的角速度,問所有齒輪中最大的角速度的自然對數是多少。
解法:根據齒輪之間的連線關係(共角速度或者共線速度)建圖,我們就得到了一片森林。每一棵樹任取一個點作為參照點,然後對於操作物件所在的樹單獨考慮。先討論操作1,如果被修改的節點的父節點和該節點是共角速度的,那麼這個修改操作只會影響這個所有與這個節點共線速度的節點。如果該節點與父節點共線速度,那麼操作會影響該節點以及所有與該節點共角速度的點。對於操作2,我們只需要減去這個點相對於參照點的值,然後再加上所在樹的最大權值即可。
這裡有兩個trick:
1.由於每一個齒輪的半徑一定是2的冪次,所以可以對半徑直接取log2,那麼我們每一次操作都變成了整數之間的運算,結果乘上log(2.0)就行,又好寫又快~
2.對於每一個節點,把這個節點所有連線的點排序,使得和該點共角速度的點在對應vector中的字首裡,這樣我們做修改操作的時候就可以分成兩個區間討論了。
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100005;
const double EPS = 1e-8;
struct Node{
int l,r,v,tag;
};
vector<vector<Node> >root;//記錄森林中的每一棵線段樹的根節點
int n,m,q,cnt,st,t,siz,bel[N],id[N],sz[N],rsz[N],f[N],r[N],bs[N];
//陣列分別代表編號為i的節點:屬於第bel[i]棵線段樹;在dfs序中的編號;子樹大小;與該節點共角速度的節點個數;父節點;半徑;與參照點的相對大小
vector<pair<int,bool> >e[N];//bool為真時表示共角速度,反之為共線速度
bool vis[N];
int Log(int k){
int res=0;
while(k!=1){
k/=2;
res++;
}
return res;
}
inline bool cmp(const pair<int,bool>& q,const pair<int,bool>& w){
if(q.second!=w.second)
return q.second;
return q.first>w.first;
}
void dfs(int last,int now,int bias){
f[now]=(last==-1?now:last);
id[now]=st++;
bel[now]=cnt;
sz[now]=1;
rsz[now]=1;
bs[now]=bias;
for(int i=0;i<e[now].size();i++)
if(!vis[e[now][i].first]&&e[now][i].first!=last){
vis[e[now][i].first]=true;
dfs(now,e[now][i].first,bias+(e[now][i].second?0:r[now]-r[e[now][i].first]));
sz[now]+=sz[e[now][i].first];
rsz[now]+=(e[now][i].second?1:0)*sz[e[now][i].first];
}
}
void Build(int ps,int i,int l,int r){
root[ps][i].l=l;
root[ps][i].r=r;
root[ps][i].tag=root[ps][i].v=0;
if(l==r)
return ;
int mid=l+r>>1;
Build(ps,i<<1,l,mid);
Build(ps,i<<1|1,mid+1,r);
}
inline void PushUp(int ps,int i){
root[ps][i].v=max(root[ps][i<<1].v,root[ps][i<<1|1].v);
}
inline void PushDown(int ps,int i){
if(root[ps][i].tag){
root[ps][i<<1].v+=root[ps][i].tag;
root[ps][i<<1].tag+=root[ps][i].tag;
root[ps][i<<1|1].v+=root[ps][i].tag;
root[ps][i<<1|1].tag+=root[ps][i].tag;
root[ps][i].tag=0;
}
}
void Ist(int ps,int i,int x,int val){
if(root[ps][i].l==x&&root[ps][i].r==x){
root[ps][i].v=val;
return ;
}
if(x<=root[ps][i<<1].r)
Ist(ps,i<<1,x,val);
else if(root[ps][i<<1|1].l<=x)
Ist(ps,i<<1|1,x,val);
PushUp(ps,i);
}
void Update(int ps,int i,int l,int r,int bias){
if(l>r)
return ;
if(l<=root[ps][i].l&&root[ps][i].r<=r){
root[ps][i].v+=bias;
root[ps][i].tag+=bias;
return ;
}
PushDown(ps,i);
if(l<=root[ps][i<<1].r)
Update(ps,i<<1,l,r,bias);
if(root[ps][i<<1|1].l<=r)
Update(ps,i<<1|1,l,r,bias);
PushUp(ps,i);
}
int Query(int ps,int i,int l,int r){
if(l<=root[ps][i].l&&root[ps][i].r<=r)
return root[ps][i].v;
PushDown(ps,i);
if(r<=root[ps][i<<1].r)
return Query(ps,i<<1,l,r);
else if(root[ps][i<<1|1].l<=l)
return Query(ps,i<<1|1,l,r);
else
return max(Query(ps,i<<1,l,r),Query(ps,i<<1|1,l,r));
}
int main(){
int cas=1,a,x,y;
while(scanf("%d %d %d",&n,&m,&q)==3){
memset(vis,false,sizeof vis);
root.clear();
cnt=0;
for(int i=1;i<=n;i++){
e[i].clear();
scanf("%d",&r[i]);
r[i]=Log(r[i]);
}
for(int i=1;i<=m;i++){
scanf("%d %d %d",&a,&x,&y);
a--;
e[x].push_back(make_pair(y,a));
e[y].push_back(make_pair(x,a));
}
for(int i=1;i<=n;i++)
sort(e[i].begin(),e[i].end(),cmp);
for(int i=1;i<=n;i++)
if(!vis[i]){
vis[i]=true;
st=1;
dfs(-1,i,0);
root.push_back(vector<Node>(sz[i]<<2));
Build(cnt++,1,1,sz[i]);
}
for(int i=1;i<=n;i++)
Ist(bel[i],1,id[i],bs[i]);
printf("Case #%d:\n",cas++);
while(q--){
scanf("%d %d %d",&a,&x,&y);
t=Log(y);
if(a==1){
if(f[x]==x||(id[f[x]]<id[x]&&id[x]<id[f[x]]+rsz[f[x]]))
Update(bel[x],1,id[x]+rsz[x],id[x]+sz[x]-1,t-r[x]);//更新與該節點共線速度的子節點
else
Update(bel[x],1,id[x],id[x]+rsz[x]-1,r[x]-t);//更新與該節點共角速度的子節點
r[x]=t;
}else
printf("%.3f\n",log(2.0)*(t-Query(bel[x],1,id[x],id[x])+Query(bel[x],1,1,root[bel[x]][1].r)));
}
}
return 0;
}
相關文章
- 2018 Multi-University Training Contest 3 - HDU ContestAI
- HDU 5235 Friends (2015 Multi-University Training Contest 2 搜尋+剪枝)AI
- 2018 Multi-University Training Contest 9----hdu 6415 Rikka with Nash EquilibriumAIUI
- HDU-2016 Multi-University Training Contest 3-Sqrt Bo-大數開方AI
- 【HDU5734 2016 Multi-University Training Contest 2A】【公式代入推導】Acperience n維向量各有加減最小模長AI公式
- 【HDU5735 2016 Multi-University Training Contest 2B】【暴力做法 + 折半法】Born Slippy 祖先鏈的最大運算權值AI
- 【HDU5738 2016 Multi-University Training Contest 2E】【平面點數計數 共線判定】Eureka 平面有多少個集合滿足貢獻AI
- hdu1258 Sum It Up (DFS)
- The 2024 Hunan Multi-School Programming Training Contest, Round 4NaNAI
- HDU 2017 字串統計字串
- HDU4091(2011 Asia Shanghai Regional Contest)AI
- 2017-2018 ACM-ICPC Southeast Regional Contest (Div. 1)ACMAST
- 2017 United Kingdom and Ireland Programming Contest (UKIEPC 2017)
- 2017中國大學生程式設計競賽 - 女生專場(SDKD 2024 Summer Training Contest K2)程式設計AI
- 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)ACM
- Laravel: Up and Running (1):介紹Laravel
- GYOI Beginning Contest #1 -zh
- Petrozavodsk Summer-2017. Moscow IPT Contest
- 2017 ACM Jordanian Collegiate Programming ContestACM
- Contest5400 - 網路流-1
- HDU3714 Error Curves(2010 Asia Chengdu Regional Contest)Error
- single 與 up to 1 rows的區別
- 2020HDU多校第三場 1005 Little W and Contest
- 2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)ACM
- AtCoder Regular Contest 121 D - 1 or 2
- HDU 1258Sum It Up(暴力dfs,記住相同的狀態只保留一個)
- 2017-2018 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2017)ACM
- 2016-2017 ACM-ICPC, NEERC, Southern Subregional ContestACM
- 2016-2017 ACM-ICPC, NEERC, Northern Subregional ContestACM
- 2017-2018 ACM-ICPC, NEERC, Southern Subregional ContestACM
- 2017-2018 ACM-ICPC, NEERC, Northern Subregional ContestACM
- wake up
- Level Up
- recovery training articleAI
- 2016-2017 ACM-ICPC, NEERC, Moscow Subregional ContestACM
- 2016-2017 ACM-ICPC Asia-Bangkok Regional ContestACM
- 2017-2018 ACM-ICPC, NEERC, Moscow Subregional ContestACM
- 2014上海網路賽1004||hdu5045 contest【狀態壓縮dp】