wannafly 练习赛11 F 求子树(树上莫队+换根)
链接:https://www.nowcoder.com/acm/contest/59/F
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
64bit IO Format: %lld
题目描述
给一个n个点的树,第i个点的值是vi,初始根是1。
有m个操作,每次操作:
1.将树根换为x。
2.给出两个点x,y,求所有点对(a,b)的个数满足a在x子树中,b在y子树中,va==vb
输入描述:
第一行两个数表示n,m
第二行n个数,表示每个点的点权vi
之后n-1行,每行两个数x,y表示一条边
之后m行,每行为:
1 x表示把根换成x点
2 x y表示查询x点的子树与y点的子树
输出描述:
对于每个询问,输出一行一个数表示答案
示例1
输入
5 5 1 2 3 4 5 1 2 1 3 3 4 3 5 2 4 5 2 1 5 2 3 5 1 5 2 4 5
输出
0 1 1 1
备注:
对于100%的数据,1 <= n <= 1e5 , 1<= m <= 5e5 , 1 <= vi<= 1e9
/////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
不是很懂,,一直超时,可能被卡常数了,,但是不想再码了,很绝望,不辜负自己码并且调那么久,还是把自己的超时代码发上来
1 #include<cstdio> 2 #include<algorithm> 3 #define mst(a,b) memset((a),(b), sizeof a) 4 #define lowbit(a) ((a)&(-a)) 5 #define IOS ios::sync_with_stdio(0);cin.tie(0); 6 using namespace std; 7 typedef long long ll; 8 typedef unsigned long long ull; 9 typedef pair<int,int> pii; 10 const int mod=1e9+7; 11 const int maxn=1e5+10; 12 const int maxm=8e6; 13 int n,m; 14 int val[maxn],mx; 15 pii use[maxn]; 16 void init_val(){ 17 for(int i=1;i<=n;++i)use[i].first=val[i],use[i].second=i; 18 sort(use+1,use+1+n); 19 int cc=2; 20 val[use[1].second]=1; 21 for(int i=2;i<=n;++i){ 22 if(use[i].first==use[i-1].first)val[use[i].second]=cc-1; 23 else val[use[i].second]=cc++; 24 } 25 } 26 vector<int>to[maxn]; 27 int dfsn[maxn],cnt; 28 29 pii mine[maxn][2];int v[maxn]; 30 31 inline void dfs(int pos,int fa){ 32 int le,ri; 33 dfsn[++cnt]=pos; 34 le=cnt; 35 for(int i=0;i<to[pos].size();++i)if(to[pos][i]!=fa)dfs(to[pos][i],pos); 36 ri=cnt; 37 mine[pos][0] = make_pair(le,ri); 38 } 39 40 struct node{ 41 int id,a,b; 42 node(int _id,int _a,int _b){id=_id,a=_a,b=_b;} 43 }; 44 vector<node>w[maxn]; 45 ll ans[maxn<<3],cc; 46 struct query{ 47 int foo,l,r,bel;bool ti; 48 query(int a=0,bool b=0,int c=0,int d=0):foo(a),ti(b),l(c),r(d){}; 49 }; 50 query all[maxm];int sz; 51 52 inline void add_q(int l1,int r1,int l2,int r2,int foo){ 53 if(r1&&r2) all[++sz]=query(foo,true,min(r1,r2),max(r1,r2)); 54 if(l1-1&&r2) all[++sz]=query(foo,false,min(l1-1,r2),max(l1-1,r2)); 55 if(l2-1&&r1) all[++sz]=query(foo,false,min(l2-1,r1),max(l2-1,r1)); 56 if(l1-1&&l2-1) all[++sz]=query(foo,true,min(l1-1,l2-1),max(l1-1,l2-1)); 57 } 58 59 inline void add_query(int a,int b,int foo){ 60 for(int i=0;i<v[a];++i)for(int j=0;j<v[b];++j) 61 add_q(mine[a][i].first,mine[a][i].second,mine[b][j].first,mine[b][j].second,foo); 62 } 63 inline void change(int from,int to){ 64 v[from]=0; 65 if(v[to]==2){ 66 mine[from][v[from]++] = make_pair(mine[to][0].second+1,mine[to][1].first-1); 67 }else{ 68 if(mine[to][0].first!=1) 69 mine[from][v[from]++] = make_pair(1,mine[to][0].first-1); 70 if(mine[to][0].second!=n) 71 mine[from][v[from]++] = make_pair(mine[to][0].second+1,n); 72 73 } 74 v[to]=1; 75 mine[to][0] = make_pair(1,n); 76 } 77 inline void getq(int pos,int fa){ 78 for(int i=0;i<w[pos].size();++i) 79 add_query(w[pos][i].a , w[pos][i].b , w[pos][i].id); 80 81 for(int i=0;i<to[pos].size();++i){ 82 int tt=to[pos][i]; 83 if(tt==fa)continue; 84 pii g =mine[tt][0]; 85 change(pos,tt); 86 getq(tt,pos); 87 v[tt]=v[pos]=1; 88 mine[tt][0]=g,mine[pos][0]=make_pair(1,n); 89 } 90 } 91 int blo; 92 int x[maxm],y[maxm],c[maxm]; 93 94 int lt[maxn],rt[maxn]; 95 int main() { 96 #ifdef local 97 freopen("inpp","r",stdin); 98 // freopen("outpp","w",stdout); 99 #endif 100 scanf("%d%d",&n,&m); 101 for(int i=1;i<=n;++i)scanf("%d",&val[i]),v[i]=1; 102 init_val(); 103 for(int i=1;i<n;++i){ 104 int a,b;scanf("%d%d",&a,&b); 105 to[a].push_back(b);to[b].push_back(a); 106 } 107 dfs(1,0); 108 int now=1; 109 while(m--){ 110 int od,a,b; 111 scanf("%d",&od); 112 if(od==1)scanf("%d",&now); 113 else{ 114 scanf("%d%d",&a,&b);++cc; 115 w[now].push_back(node(cc,a,b)); 116 } 117 } 118 getq(1,0); 119 blo=sqrt(sz);if(blo==0)blo=1; 120 for(int i=1;i<=sz;++i)all[i].bel=all[i].l/blo; 121 122 for(int i=1;i<=sz;++i)++c[all[i].r];//基数排序部分 123 for(int i=1;i<=n;++i)c[i]+=c[i-1]; 124 for(int i=1;i<=sz;++i)y[c[all[i].r]--]=i; 125 126 int en=n/blo; 127 for(int i=0;i<=en;++i)c[i]=0; 128 for(int i=1;i<=sz;++i)++c[all[i].bel]; 129 for(int i=1;i<=en;++i)c[i]+=c[i-1]; 130 for(int i=sz;i;--i)x[ c[ all[y[i]].bel ]-- ]=y[i]; 131 132 ll uu=0; 133 134 int L=0,R=0; 135 136 for(int i=1;i<=sz;++i){ 137 query&ha=all[x[i]]; 138 while(R<ha.r){ 139 ++R; 140 int k=val[dfsn[R]]; 141 uu-=(ll)rt[k]*lt[k]; 142 ++rt[k]; 143 uu+=(ll)rt[k]*lt[k]; 144 } 145 while(R>ha.r){ 146 int k=val[dfsn[R]]; 147 uu-=(ll)rt[k]*lt[k]; 148 --rt[k]; 149 uu+=(ll)rt[k]*lt[k]; 150 --R; 151 } 152 while(L>ha.l){ 153 int k=val[dfsn[L]]; 154 uu-=(ll)rt[k]*lt[k]; 155 --lt[k]; 156 uu+=(ll)rt[k]*lt[k]; 157 --L; 158 } 159 while(L<ha.l){ 160 ++L; 161 int k=val[dfsn[L]]; 162 uu-=(ll)rt[k]*lt[k]; 163 ++lt[k]; 164 uu+=(ll)rt[k]*lt[k]; 165 } 166 if(ha.ti)ans[ha.foo]+=uu; 167 else ans[ha.foo]-=uu; 168 } 169 for(int i=1;i<=cc;++i) 170 printf("%lld\n",ans[i]); 171 return 0; 172 }