wannafly 练习赛11 F 求子树(树上莫队+换根)

链接:https://www.nowcoder.com/acm/contest/59/F

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 262144K,其他语言524288K
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 }

 

posted on 2018-03-07 21:45  scau_bi  阅读(350)  评论(0编辑  收藏  举报

导航