没错,这就是上次联考的D1T3逃离……
从昨天下午就开始写了,写了快一天,到现在终于过了……
我做这题最大的感想就是:我衷心祝愿出题人全家身体健康……(咳闹着玩的,其实我也出过毒瘤题……
看看代码长度,你们大概就能理解我的心情了……
不多说了放代码,注释我懒得删了,不要介意……
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cassert> 5 #include<ext/pb_ds/assoc_container.hpp> 6 #include<ext/pb_ds/tree_policy.hpp> 7 #include<ext/pb_ds/priority_queue.hpp> 8 #define isroot(x) ((x)->p==null||((x)!=(x)->p->ch[0]&&(x)!=(x)->p->ch[1])) 9 #define dir(x) ((x)==(x)->p->ch[1]) 10 using namespace std; 11 using namespace __gnu_pbds; 12 const int maxn=100010; 13 const long long INF=1000000000000000000ll; 14 struct binary_heap{ 15 __gnu_pbds::priority_queue<long long,less<long long>,binary_heap_tag>q1,q2; 16 binary_heap(){} 17 void push(long long x){if(x>(-INF)>>2)q1.push(x);} 18 void erase(long long x){if(x>(-INF)>>2)q2.push(x);} 19 long long top(){ 20 if(empty())return -INF; 21 while(!q2.empty()&&q1.top()==q2.top()){ 22 q1.pop(); 23 q2.pop(); 24 } 25 return q1.top(); 26 } 27 long long top2(/* bool flag=false */){ 28 if(size()<2)return -INF; 29 long long a=top(); 30 erase(a); 31 long long b=top();//if(flag)printf("(a=%I64d b=%I64d) ",a,b); 32 push(a); 33 return a+b; 34 } 35 int size(){return q1.size()-q2.size();} 36 bool empty(){return q1.size()==q2.size();} 37 }heap;//全局堆维护每条链的最大子段和 38 struct node{ 39 long long sum,maxsum,prefix,suffix; 40 int key; 41 binary_heap heap;//每个点的堆存的是它的子树中到它的最远距离,如果它是黑点的话还会包括自己 42 node *ch[2],*p; 43 bool rev; 44 node(int k=0):sum(k),maxsum(-INF),prefix(-INF),suffix(-INF),key(k),rev(false){} 45 inline void pushdown(){ 46 if(!rev)return; 47 ch[0]->rev^=true; 48 ch[1]->rev^=true; 49 swap(ch[0],ch[1]); 50 swap(prefix,suffix); 51 rev=false; 52 } 53 inline void refresh(){//assert(!rev); 54 pushdown(); 55 ch[0]->pushdown(); 56 ch[1]->pushdown(); 57 sum=ch[0]->sum+ch[1]->sum+key; 58 prefix=max(ch[0]->prefix,ch[0]->sum+key+ch[1]->prefix); 59 suffix=max(ch[1]->suffix,ch[1]->sum+key+ch[0]->suffix); 60 maxsum=max(max(ch[0]->maxsum,ch[1]->maxsum),ch[0]->suffix+key+ch[1]->prefix); 61 if(!heap.empty()){ 62 prefix=max(prefix,ch[0]->sum+key+heap.top()); 63 suffix=max(suffix,ch[1]->sum+key+heap.top()); 64 maxsum=max(maxsum,max(ch[0]->suffix,ch[1]->prefix)+key+heap.top()); 65 if(heap.size()>1){ 66 /* int a=heap.top(); 67 heap.erase(a); */ 68 maxsum=max(maxsum,heap.top2()+key); 69 /* heap.push(a); */ 70 } 71 } 72 /* pushdown(); 73 ch[0]->pushdown(); 74 ch[1]->pushdown(); 75 long long lm=ch[0]->maxsum,rm=ch[1]->maxsum; 76 long long llm=ch[0]->prefix,rrm=ch[1]->suffix,lrm=ch[0]->suffix,rlm=ch[1]->prefix; 77 long long lsum=ch[0]->sum,rsum=ch[1]->sum; 78 long long k=heap.top()+key; 79 80 maxsum=max(max(max(lm,rm),rlm+lrm+key),max(lrm,rlm)+k); 81 maxsum=max(maxsum,heap.top2()+key); 82 //if (p->mx<0) p->mx=-inf; 83 84 prefix=max(llm,lsum+max(key+rlm,k)); 85 //if (p->lmx<0) p->lmx=-inf; 86 suffix=max(rrm,rsum+max(key+lrm,k)); 87 //if (p->rmx<0) p->rmx=-inf; 88 89 sum=lsum+rsum+key; */ 90 } 91 }null[maxn<<1],*ptr=null; 92 void addedge(int,int,int); 93 void deledge(int,int); 94 void modify(int,int,int); 95 void modify_color(int); 96 node *newnode(int); 97 node *access(node*); 98 void makeroot(node*); 99 void link(node*,node*); 100 void cut(node*,node*); 101 void splay(node*); 102 void rot(node*,int); 103 queue<node*>freenodes; 104 tree<pair<int,int>,node*>mp; 105 bool col[maxn]={false}; 106 char c; 107 int n,m,k,x,y,z; 108 int main(){ 109 null->ch[0]=null->ch[1]=null->p=null; 110 scanf("%d%d%d",&n,&m,&k); 111 for(int i=1;i<=n;i++){ 112 newnode(0); 113 //heap.push(-0x3f3f3f3f); 114 } 115 heap.push(0); 116 while(k--){ 117 scanf("%d",&x); 118 col[x]=true; 119 null[x].heap.push(0); 120 }//print_all(); 121 for(int i=1;i<n;i++){ 122 scanf("%d%d%d",&x,&y,&z); 123 if(x>y)swap(x,y); 124 addedge(x,y,z);//printf("%d ",heap.top());print_all(); 125 } 126 //printf("---------------------------------OK!!!--------------------------------- "); 127 while(m--){ 128 scanf(" %c%d",&c,&x); 129 if(c=='A'){ 130 scanf("%d",&y); 131 if(x>y)swap(x,y); 132 deledge(x,y); 133 } 134 else if(c=='B'){ 135 scanf("%d%d",&y,&z); 136 if(x>y)swap(x,y); 137 addedge(x,y,z); 138 } 139 else if(c=='C'){ 140 scanf("%d%d",&y,&z); 141 if(x>y)swap(x,y); 142 modify(x,y,z); 143 } 144 else modify_color(x);//printf("size=%d ",heap.size()); 145 printf("%lld ",(heap.top()>0?heap.top():-1));//print_all(); 146 } 147 return 0; 148 } 149 void addedge(int x,int y,int z){//printf("addedge(%d,%d,%d) ",x,y,z); 150 node *tmp; 151 if(freenodes.empty())tmp=newnode(z); 152 else{ 153 tmp=freenodes.front(); 154 freenodes.pop(); 155 *tmp=node(z); 156 } 157 tmp->ch[0]=tmp->ch[1]=tmp->p=null;heap.push(tmp->maxsum);//printf("push(%I64d) ",tmp->maxsum); 158 link(tmp,null+x); 159 link(tmp,null+y); 160 mp[make_pair(x,y)]=tmp; 161 } 162 void deledge(int x,int y){//printf("deledge(%d,%d) ",x,y); 163 node *tmp=mp[make_pair(x,y)]; 164 cut(tmp,null+x); 165 cut(tmp,null+y); 166 freenodes.push(tmp); 167 heap.erase(tmp->maxsum);//printf("erase(%I64d) ",tmp->maxsum); 168 mp.erase(make_pair(x,y)); 169 } 170 void modify(int x,int y,int z){ 171 node *tmp=mp[make_pair(x,y)]; 172 makeroot(tmp); 173 tmp->pushdown(); 174 heap.erase(tmp->maxsum);//printf("erase(%I64d) ",tmp->maxsum); 175 tmp->key=z; 176 tmp->refresh(); 177 heap.push(tmp->maxsum);//printf("push(%I64d) ",tmp->maxsum); 178 } 179 void modify_color(int x){ 180 makeroot(null+x); 181 col[x]^=true; 182 if(col[x])null[x].heap.push(0); 183 else null[x].heap.erase(0); 184 heap.erase(null[x].maxsum);//printf("erase(%I64d) ",null[x].maxsum); 185 null[x].refresh(); 186 heap.push(null[x].maxsum);//printf("push(%I64d) ",null[x].maxsum); 187 } 188 node *newnode(int k){ 189 *(++ptr)=node(k); 190 ptr->ch[0]=ptr->ch[1]=ptr->p=null; 191 return ptr; 192 } 193 node *access(node *x){ 194 splay(x);//printf("access(%d) ",x-null); 195 heap.erase(x->maxsum);//printf("erase(%I64d) ",x->maxsum); 196 x->refresh();//printf("x->maxsum=%I64d key=%d top()=%I64d x->heap.top()+key+ch[1]->prefix=%I64d ",x->maxsum,x->key,x->heap.top(),x->heap.top()+x->key+x->ch[1]->prefix); 197 if(x->ch[1]!=null){ 198 x->ch[1]->pushdown(); 199 x->heap.push(x->ch[1]->prefix);x->refresh();//printf("x.heap.push(%I64d) top()=%I64d top2()=%I64d size=%d lc->suffix=%I64d ",x->ch[1]->prefix,x->heap.top(),x->heap.top2(x==null+108),x->heap.size(),x->ch[0]->suffix); 200 heap.push(x->ch[1]->maxsum);//printf("push(%I64d) ",x->ch[1]->maxsum); 201 } 202 x->ch[1]=null; 203 x->refresh();//printf("x->maxsum=%I64d ",x->maxsum); 204 node *y=x; 205 x=x->p;//printf("Begin! "); 206 while(x!=null){ 207 splay(x);//printf("x=%d y=%d ",x-null,y-null); 208 heap.erase(x->maxsum);//printf("erase(%I64d) ",x->maxsum); 209 if(x->ch[1]!=null){ 210 x->ch[1]->pushdown(); 211 x->heap.push(x->ch[1]->prefix); 212 heap.push(x->ch[1]->maxsum);//printf("push(%I64d) ",x->ch[1]->maxsum); 213 } 214 x->heap.erase(y->prefix); 215 x->ch[1]=y; 216 (y=x)->refresh();//printf("maxsum=%I64d ",y->maxsum); 217 x=x->p; 218 }//printf("Final "); 219 heap.push(y->maxsum);//printf("push(%I64d) ",y->maxsum);printf("Finished! "); 220 return y; 221 } 222 void makeroot(node *x){ 223 access(x); 224 splay(x); 225 x->rev^=true; 226 } 227 void link(node *x,node *y){//新添一条虚边,维护y对应的堆 228 //printf("link(%d,%d) ",x-null,y-null); 229 makeroot(x); 230 makeroot(y); 231 x->pushdown(); 232 x->p=y; 233 heap.erase(y->maxsum);//printf("erase(%I64d) ",y->maxsum); 234 y->heap.push(x->prefix); 235 y->refresh(); 236 heap.push(y->maxsum);//printf("push(%I64d) ",y->maxsum); 237 //printf("now top()=%I64d ",(heap.empty()?-1:heap.top())); 238 } 239 void cut(node *x,node *y){//断开一条实边,一条链变成两条链,需要维护全局堆 240 makeroot(x);//printf("cut(%d,%d) ",x-null,y-null); 241 access(y); 242 splay(y); 243 heap.erase(y->maxsum);//printf("erase(%I64d) ",y->maxsum); 244 heap.push(y->ch[0]->maxsum);//printf("push(%I64d) ",y->ch[0]->maxsum); 245 y->ch[0]->p=null; 246 y->ch[0]=null; 247 y->refresh(); 248 heap.push(y->maxsum);//printf("push(%I64d) ",y->maxsum); 249 //printf("now top()=%I64d ",(heap.empty()?-1:heap.top())); 250 } 251 void splay(node *x){ 252 /* static node *s[maxn<<1]; 253 int top=0; 254 node *u=x; 255 while(!isroot(u)){ 256 s[++top]=u; 257 u=u->p; 258 } 259 u->pushdown(); 260 while(top)s[top--]->pushdown(); */ 261 x->pushdown(); 262 while(!isroot(x)){ 263 if(!isroot(x->p))x->p->p->pushdown(); 264 x->p->pushdown(); 265 x->pushdown(); 266 if(isroot(x->p)){ 267 rot(x->p,dir(x)^1); 268 break; 269 } 270 if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1); 271 else rot(x->p,dir(x)^1); 272 rot(x->p,dir(x)^1); 273 } 274 } 275 void rot(node *x,int d){ 276 node *y=x->ch[d^1]; 277 if((x->ch[d^1]=y->ch[d])!=null)y->ch[d]->p=x; 278 y->p=x->p; 279 if(!isroot(x))x->p->ch[dir(x)]=y; 280 (y->ch[d]=x)->p=y; 281 x->refresh(); 282 y->refresh(); 283 }
UPD:
在虚拟机里跑结果TLE了(跑的非常慢,20s都出不来),然后把pb_ds换成std::map和std::priority_queue就过了= =
真是玄学,用pb_ds在win7跑的飞快(好吧其实跟std::对应数据结构速度基本一样),但是在Linux里感觉复杂度降了一级……
这个故事告诉我们,没事不要乱玩pb_ds,乖乖用std::……