【GDSOI 2017】【JZOJ 5107】中學生資料結構題
Description
給出一棵帶權有根樹,要求:
1. 樹上的路徑區間加
2. 樹上路徑區間查詢和
3. 樹上路徑整體旋轉一位(如:原路徑上的權值依次是這樣的:1,2,3,4,操作完後變成:4,1,2,3)
n<=100000
時限:2S
Solution
這顯然是鏈剖套Splay嘛,
旋轉就相當於刪掉最後一個,加到前面去,
聽說LCT更簡單
複雜度:
O(n\log(n))
Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
using namespace std;
typedef long long LL;
const int N=100500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
int B[2*N][2],A[N],B0;
struct qqww
{
int fa,lt,zx,si,c;
}a[N];
struct qwqw
{
int l,r,fa,si,la;
LL v,sum;
}b[N];
int root,b0;
void link(int q,int w)
{
B[++B0][0]=A[q];A[q]=B0,B[B0][1]=w;
B[++B0][0]=A[w];A[w]=B0,B[B0][1]=q;
}
int dfsf(int q,int fa,int c)
{
a[q].fa=fa,a[q].si=1;a[q].c=c;
efo(i,q)if(B[i][1]!=fa)a[q].si+=dfsf(B[i][1],q,c+1);
return a[q].si;
}
void dfs(int q,int fa,int lt)
{
a[q].lt=(lt?lt:lt=q);
a[q].zx=++b0;
int mx=0;
efo(i,q)if(B[i][1]!=fa)if(a[mx].si<a[B[i][1]].si)mx=B[i][1];
if(mx)dfs(mx,q,lt);
efo(i,q)if(B[i][1]!=fa&&B[i][1]!=mx)dfs(B[i][1],q,0);
}
bool SD(int q){return q==b[b[q].fa].r;}
void merge(int q)
{
b[q].si=b[b[q].l].si+1+b[b[q].r].si;
b[q].sum=b[b[q].l].sum+b[q].v+b[b[q].r].sum;
}
void doit(int q)
{
if(!b[q].la)return;
b[q].v+=b[q].la;
b[q].sum+=(LL)b[q].si*(LL)b[q].la;
if(b[q].l)b[b[q].l].la+=b[q].la;
if(b[q].r)b[b[q].r].la+=b[q].la;
b[q].la=0;
}
void rotate(int q)
{
int t=b[q].fa;
if(!SD(q))
{
b[t].l=b[q].r;
b[b[q].r].fa=t;
b[q].r=t;
}else
{
b[t].r=b[q].l;
b[b[q].l].fa=t;
b[q].l=t;
}
if(SD(t))b[b[t].fa].r=q;
else b[b[t].fa].l=q;
b[q].fa=b[t].fa;
b[t].fa=q;
merge(t);
merge(q);
b[0].l=b[0].r=b[0].fa=0;
}
int Splay(int q,int T)
{
while(b[q].fa!=T)
{
if(b[b[q].fa].fa!=T)
if(SD(q)==SD(b[q].fa))rotate(b[q].fa);
else rotate(q);
rotate(q);
}
if(!T)root=q;
}
int search(int q,int w)
{
doit(b[q].l),doit(b[q].r);
if(b[b[q].l].si>=w)return search(b[q].l,w);
w-=b[b[q].l].si+1;
if(!w)return q;
return search(b[q].r,w);
}
void changea(int q,int w,int e)
{
Splay(search(root,q-1),0);
Splay(w=search(root,w+1),root);
b[b[w].l].la+=e;
doit(b[w].l);
merge(w),merge(root);
}
LL Gsum(int q,int w)
{
Splay(search(root,q-1),0);
Splay(w=search(root,w+1),root);
return b[b[w].l].sum;
}
int DLT(int q)
{
Splay(search(root,q-1),0);
Splay(q=search(root,q+1),root);
int ans=b[q].l;
b[b[q].l].fa=0;b[q].l=0;
merge(q),merge(root);
return ans;
}
void IST(int q,int w)
{
Splay(search(root,q),0);
b[w].l=0;b[w].r=b[root].r;b[w].fa=root;
b[root].r=w;if(b[w].r)b[b[w].r].fa=w;
merge(w),merge(root);
}
void SWAP_v(int q,int w)
{
if(q>w)swap(q,w);
Splay(q=search(root,q),0);
Splay(w=search(root,w),root);
swap(b[q].v,b[w].v);
merge(w),merge(q);
}
void modifya(int q,int w,int e)
{
while(a[q].lt!=a[w].lt)
{
if(a[a[q].lt].c<a[a[w].lt].c)swap(q,w);
int t=a[q].lt;
changea(a[t].zx,a[q].zx,e);
q=a[t].fa;
}
if(a[q].c<a[w].c)swap(q,w);
changea(a[w].zx,a[q].zx,e);
}
LL find(int q,int w)
{
LL ans=0;
while(a[q].lt!=a[w].lt)
{
if(a[a[q].lt].c<a[a[w].lt].c)swap(q,w);
int t=a[q].lt;
ans+=Gsum(a[t].zx,a[q].zx);
q=a[t].fa;
}
if(a[q].c<a[w].c)swap(q,w);
return ans+Gsum(a[w].zx,a[q].zx);
}
int c1[N][2],c2[N][2],c10,c20;
void change_shift(int q,int w)
{
if(q==w)return;
swap(q,w);c10=c20=0;
while(a[q].lt!=a[w].lt)
{
if(a[a[q].lt].c>a[a[w].lt].c)c1[++c10][0]=q,c1[c10][1]=a[q].lt,q=a[a[q].lt].fa;
else c2[++c20][1]=w,c2[c20][0]=a[w].lt,w=a[a[w].lt].fa;
}
if(a[q].c>a[w].c)c1[++c10][0]=q,c1[c10][1]=w;
else c2[++c20][1]=w,c2[c20][0]=q;
q=w=0;
fo(i,1,c10)
{
q=c1[i][0],w=c1[i][1];
int q1=DLT(a[q].zx);
IST(a[w].zx-1,q1);
if(i!=c10)SWAP_v(a[w].zx,a[c1[i+1][0]].zx);
}
int t=w;
for(;c20;c20--)
{
q=c2[c20][0],w=c2[c20][1];
if(t)SWAP_v(a[t].zx,a[q].zx);
int q1=DLT(a[q].zx);
IST(a[w].zx-1,q1);
t=w;
}
}
int main()
{
freopen("shift.in","r",stdin);
freopen("shift.out","w",stdout);
int q,w,e;
read(n);
fo(i,1,n-1)read(q),read(w),link(q,w);
dfsf(1,0,1);
b0=root=1;
dfs(1,0,0);
fo(i,1,n+1)b[i].r=i+1,b[i+1].fa=i,b[i].si=n+2-i+1;
b[n+2].si=1;b0++;
read(m);
fo(i,1,m)
{
char ch=' ';
while(ch<'A'||ch>'Z')ch=getchar();
if(ch=='A')
{
read(q),read(w),read(e);
modifya(q,w,e);
}else if(ch=='S')
{
read(q),read(w);
change_shift(q,w);
}else
{
read(q),read(w);
printf("%lld\n",find(q,w));
}
}
return 0;
}
相關文章
- jzoj5249 【NOIP2017提高A組模擬8.10】文字編輯器 (序列修改類問題,資料結構)資料結構
- 資料結構課程設計——學生資訊管理系統資料結構
- Python原生資料結構增強模組collectionsPython資料結構
- 好題——數學與資料結構資料結構
- 資料結構專題頁(更新中...)資料結構
- 資料結構學習之樹結構資料結構
- 我的學生資訊管理系統總結
- 學生資訊管理系統之SQL連結SQL
- 學《資料結構》有感資料結構
- 資料結構學習資料結構
- 資料結構中樹形結構簡介資料結構
- Jzoj5459【NOIP2017提高A組衝刺11.7】密室
- 【整理】資料結構——題目資料結構
- 資料結構簡單題資料結構
- 資料結構學習--連結串列資料結構
- 資料結構學習總結--圖資料結構
- 在 JavaScript 中學習資料結構與演算法JavaScript資料結構演算法
- 資料結構學習心得資料結構
- 學生資料庫建立的開始階段資料庫
- Redis中的資料結構Redis資料結構
- oracle 中的資料結構Oracle資料結構
- JavaScript 中的 資料結構JavaScript資料結構
- 統計學生資訊(使用動態連結串列完成)
- 資料結構連結串列筆試題資料結構筆試
- leetcode演算法資料結構題解---資料結構LeetCode演算法資料結構
- js 中基礎資料結構陣列去重問題JS資料結構陣列
- 資料結構面試100題資料結構面試
- 資料結構演算法題資料結構演算法
- 資料結構專題練習資料結構
- [做題筆記] 資料結構筆記資料結構
- 重學資料結構(二、棧)資料結構
- 重學資料結構之棧資料結構
- 重學資料結構(七、圖)資料結構
- 資料結構學習筆記資料結構筆記
- 【學生資訊管理系統】總結--這只是個開始
- Java刷題常用的資料結構總結Java資料結構
- 資料結構連結串列各種問題資料結構
- C#中的資料結構C#資料結構