[考試反思]0516省選模擬98:等待

前兩個是同一道題合計$100pts$。然後我個弱智沒寫快讀被卡常丟了$40$。

(就算改成scanf("%s")然後再去模擬進制都能$AC$,原理不明,只是讀整數太慢了)

看到這套題感覺題目看起來特別麻煩然後就慫了,大概是在摸魚。

前一兩個小時可能都沒怎麼動腦子(麻木),然後回過神來發現$T1$好像沒有想象中那麼噁心。

但是感覺複雜度好像不太對,也沒想啥反正就是交上去了。

然後繼續摸魚。

嘗試想$T3$來着。但是腦子動不起來,於是打$10pts$跑路。$T2$會$10pts$但是好像挺麻煩

所以嫌少就直接扔掉了。。。

狀態又變差了。。。可能是想放個假。。。或者開個學

 

T1:Bohemian Rhapsody

大意:維護$m$棵樹,每棵樹最開始都一樣,支持操作:把第$[l,r]$棵樹上$(u,v)$路徑的所有邊長度改爲$0$。

所有操作結束後,詢問每棵樹的 所有點對距離和。$n,m,q \le 5 \times 10^5$

同時對多棵樹搞什麼操作很麻煩就算是$O(1)$複雜度也不對。考慮差分(也就是掃描線)那麼增量的個數是有限的。

樹剖線段樹維護$size_u \times (n-size_u)$。支持區間打置零標記以及刪除一層標記。隨便寫。$O(nlog^2n)$

使用$LCT$可以做到$O(nlogn)$(說着輕巧。。)

繼續$\mod$開鴿的$fread$板子。

 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 const int mod=1000000007,S=500005;
 5 char IN[1<<26],*p=IN;
 6 int mo(int a){return a>=mod?a-mod:a;}
 7 int n,m,q,f[S],dep[S],sz[S],top[S],dfn[S],tim,son[S],fir[S],l[S<<1],to[S<<1],ec,ans,w[S],tot[S<<2],tag[S<<2];
 8 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
 9 void in(int&x){x=0;while(*p<48||*p>57)p++;while(*p>47&&*p<58)x=x*10+*p++-48;}
10 void dfs(int p,int fa){
11     sz[p]=1; f[p]=fa; dep[p]=dep[fa]+1;
12     for(int i=fir[p];i;i=l[i])if(to[i]!=fa){
13         dfs(to[i],p); sz[p]+=sz[to[i]];
14         if(sz[to[i]]>sz[son[p]])son[p]=to[i];
15     }
16 }
17 void DFS(int p,int tp){
18     top[p]=tp; dfn[p]=++tim; top[p]=tp;
19     if(son[p])DFS(son[p],tp);
20     for(int i=fir[p];i;i=l[i])if(!dfn[to[i]])DFS(to[i],to[i]);
21     for(int i=fir[p];i;i=l[i])if(to[i]!=f[p])w[dfn[to[i]]]=1ll*sz[to[i]]*(n-sz[to[i]])%mod;
22 }
23 #define lc p<<1
24 #define rc lc|1
25 #define md (L+R>>1)
26 void up(int p,int L,int R){tot[p]=tag[p]?0:(L==R?w[L]:mo(tot[lc]+tot[rc]));}
27 void build(int p,int L,int R){
28     if(L==R){tot[p]=w[L];return;}
29     build(lc,L,md);build(rc,md+1,R); up(p,L,R);
30 }
31 void add(int l,int r,int v,int p=1,int L=1,int R=n){
32     if(l<=L&&R<=r)return tag[p]+=v,up(p,L,R);
33     if(l<=md)add(l,r,v,lc,L,md); if(r>md)add(l,r,v,rc,md+1,R); up(p,L,R);
34 }
35 void upd(int x,int y,int o){
36     while(top[x]!=top[y]){
37         if(dep[top[x]]<dep[top[y]])x^=y^=x^=y;
38         add(dfn[top[x]],dfn[x],o);x=f[top[x]];
39     }if(dfn[x]>dfn[y])x^=y^=x^=y;
40     if(x!=y)add(dfn[x]+1,dfn[y],o);
41 }
42 vector<int>x[S],y[S],o[S];
43 #define pb push_back
44 int main(){
45     fread(IN,1,1<<26,stdin);
46     in(n);in(m);in(q);
47     for(int i=1,a,b;i<n;++i)in(a),in(b),link(a,b),link(b,a);
48     dfs(1,0);DFS(1,1);build(1,1,n);
49     for(int i=1,a,b,u,v;i<=q;++i)in(a),in(b),in(u),in(v),
50         x[a].pb(u),y[a].pb(v),o[a].pb(1),b++,x[b].pb(u),y[b].pb(v),o[b].pb(-1);
51     for(int i=1,r=1;i<=m;++i){
52         for(int j=0;j<x[i].size();++j)upd(x[i][j],y[i][j],o[i][j]);
53         ans=(ans+1ll*(r=r*12345678ll%mod)*tot[1])%mod;
54     }printf("%d\n",ans);
55 }
View Code

 

T2:Under Pressure

題如其名。狗屁題。

因爲思路完全不着邊際所以絲毫沒有改的慾望。

 

T3:Radio Ga Ga

大意:有$m$個任務,要求你恰好在$t_i$時刻達到點$x_i$,獎勵爲$w_i$。如果你已經走過的區間是$[l,r]$那麼你下一時刻可以走到$l-1$或$r+1$。

$n$時刻恰好走完$[1,n]$。多次詢問如果你的初始區間是$[s_i,s_i]$那麼你獲得的最大獎勵是多少。$n\le 10^9,m,q \le 5 \times 10^5$

暴力$dp$的話,就是記錄一下這$m$個任務對應的$2m$個區間(標記最後經過的點是左端點還是右端點)

轉移數級別是$m^2$的。優化一下。

首先我們考慮從較大的區間轉移到較小的區間,應該是包含關係。

那麼左端點排序之後,右端點應該遞減。掃描線加一些數據結構。

爲了處理特殊情況這裏的排序很神奇:左端點升序,然後如果最後經過的點是有端點則優先,在否則如果是右端點則按長度降序,否則升序。

只要分一大堆情況討論就發現$AKT$成功解決了所有轉移的邊界限制。需要特殊處理的是如果限制的是右端點則插入數據結構的時候右端點要$-1$。

然後數據結構可以直接動態開點線段樹也可以直接離散化+樹狀數組。

然後你就處理出了每個區間的$dp$值。對於每個詢問只要找到包含它區間的最大$dp$值就可以了。

可以再來一個線段樹,也可以離線掃描線+可刪堆。注意如果限制的是左右端點則初始位置就不能是那個。同時還要考慮到長度爲$1$的區間。

我就是懶得寫線段樹了。反正複雜度都是$O(nlogn)$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define S 3333333
 4 #define ll long long
 5 int n,q,m,r[S],rc,pc;ll t[S],ans[S];
 6 unordered_map<int,ll>ex;
 7 struct P{int l,r,w,o;ll dp;}p[S];
 8 struct Qs{int x,o;}qs[S];
 9 void add(int p,ll v){for(;p;p^=p&-p)t[p]=max(t[p],v);}
10 ll ask(int p,ll a=0){for(;p<rc;p+=p&-p)a=max(a,t[p]);return a;}
11 vector<ll>v[S],V[S]; priority_queue<ll>Q,D;
12 ll top(){while(D.size()&&D.top()==Q.top())D.pop(),Q.pop();return Q.size()?Q.top():0;}
13 void lsh(int x){r[++rc]=x;r[++rc]=x-1;r[++rc]=x+1;}
14 int main(){
15     scanf("%d%d%d",&n,&m,&q);
16     for(int i=1,k,x,w;i<=m;++i){
17         scanf("%d%d%d",&k,&x,&w); lsh(x); if(k==1){ex[x]=w;continue;}
18         if(x+k-1<=n)lsh(x+k-1),p[++pc]=(P){x,x+k-1,w,0};
19         if(x-k+1>=1)lsh(x-k+1),p[++pc]=(P){x-k+1,x,w,1};
20     }
21     sort(r+1,r+1+rc); rc=unique(r+1,r+1+rc)-r; r[rc]=n+1;
22     for(int i=1;i<=pc;++i)p[i].l=lower_bound(r+1,r+rc,p[i].l)-r,p[i].r=lower_bound(r+1,r+rc,p[i].r)-r;
23     sort(p+1,p+1+pc,[](P x,P y){return x.l^y.l?x.l<y.l:(x.o^y.o?x.o>y.o:x.o^x.r-x.l<y.r-y.l);});
24     for(int i=1;i<=pc;++i)v[p[i].r+1-p[i].o].push_back(p[i].dp=ask(p[i].r)+p[i].w),V[p[i].l+1-p[i].o].push_back(p[i].dp),add(p[i].r-p[i].o,p[i].dp);
25     for(int i=1;i<=q;++i)scanf("%d",&qs[i].x),qs[i].o=i;
26     sort(qs+1,qs+1+q,[](Qs x,Qs y){return x.x<y.x;});
27     int pt=1;
28     while(pt<=q&&qs[pt].x<r[1])pt++;
29     for(int i=1;i<rc;++i){
30         for(int j=0;j<V[i].size();++j)Q.push(V[i][j]);
31         for(int j=0;j<v[i].size();++j)D.push(v[i][j]);
32         while(pt<=q&&qs[pt].x<r[i+1])ans[qs[pt].o]=top()+ex[qs[pt].x],pt++;
33     }for(int i=1;i<=q;++i)printf("%lld\n",ans[i]);
34 }
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章