[考試反思]1030csp-s模擬測試94:未知


排名也未知。第1或第5。

分數也未知,300或260。

人生真是大起大落。。。

啊啊啊啊啊我好感動啊竟然重測了一次~~~~~

評測機怎么測怎么RE,本機怎么測怎么AC(任意編譯指令,任意評測平台)

結果原來是系統棧空間開小了導致遞歸爆棧了啊。

重測就是把棧空間開到內存限制的大小然后我的代碼就沒鍋了。

然后去隔壁用評測機調了一個小時也找不到RE的原因。。。

也許是對考場上全程無摸魚一直在思考的獎勵吧。。。

然而B哥又被防AK了也是稍慘。

人生第一次AK非B組題,還是有一點激動。。。

出題人部分分給的很好,難得有提示意義。

好事就是讓我這個傻子也想出來了,壞事就是所有人的分數都很高%%%。

所以想在總分上憑這一場來翻身還是妄想。

繼續加油,沒有懈怠的機會。

畢竟又不是誰都像skyh一樣兩場不考都對排名沒影響。。。

upd:人生真是大起大落我又260了沒AK我感覺我在farting。。。為什么要這么調戲我的感情啊。。。

 

 

T1:涼宮春日的憂郁

寫高精就好了,留300位精度絕對炸不了。

其實double就夠了。求log精度更高。(好像並沒有300位+比較位數的精度高)

 1 //remember to submit
 2 #include<cstdio>
 3 int max(int a,int b){return a>b?a:b;}
 4 struct Int{
 5     long long a[50005];int ws;
 6     #define mod 1000000000000 
 7     friend void operator*=(Int &x,int p){
 8         int W=max(x.ws-25,0);
 9         for(int i=x.ws;i>=W;--i)x.a[i]*=p;
10         for(int i=W;i<=x.ws;++i)x.a[i+1]+=x.a[i]/mod,x.a[i]%=mod;
11         if(x.a[x.ws+1])x.ws++;
12     }
13     friend bool operator<=(Int x,Int y){
14         if(x.ws!=y.ws)return x.ws<y.ws;
15         for(int i=x.ws;~i;--i)if(x.a[i]!=y.a[i])return x.a[i]<y.a[i];
16         return true;
17     }
18     void reset(){
19         for(int i=ws;~i;--i)a[i]=0;
20         ws=0;a[0]=1;
21     }
22 }fc,pw;
23 int main(){
24     freopen("yuuutsu.in","r",stdin);
25     freopen("yuuutsu.out","w",stdout);
26     int t,x,y;scanf("%d",&t);
27     while(t--){
28         scanf("%d%d",&x,&y);
29         fc.reset();pw.reset();
30         while(y--)fc*=y+1,pw*=x;
31         puts(pw<=fc?"Yes":"No");
32     }
33 }
View Code

 

T2:漫無止境的八月

差分。之后操作就是在相距k的位置上一加一減。

其它位互不影響。所以把數組下標直接對k取模即可。

差分的特殊之處在於如果你對序列末尾操作的話會在位置n+1進行加減,而這個位置是幾其實是沒有關系的。

所以同余於n+1的位置是否為0不會對答案產生影響。特判。

修改的話差分數組只改變了兩個位置,判斷是否有新的0出現或消失即可。

 1 //remember to submit
 2 #include<cstdio>
 3 int n,k,q,cnt,p;long long x[2000005];
 4 int read(){
 5     register int p=0,nt=0;register char ch=getchar();
 6     while(ch<'0'||ch>'9')nt=ch=='-',ch=getchar();
 7     while(ch<='9'&&ch>='0')p=(p<<3)+(p<<1)+ch-48,ch=getchar();
 8     return nt?-p:p;
 9 }
10 int main(){
11     freopen("august.in","r",stdin);
12     freopen("august.out","w",stdout);
13     n=read();k=read();q=read();
14     for(int i=1;i<=n;++i)x[i]=read();
15     for(int i=n;i;--i)x[i]=x[i]-x[i-1];
16     for(int i=k;i<=n;++i)x[i%k]+=x[i];
17     for(int i=0;i<k;++i)if(x[i])cnt++;
18     p=(n+1)%k;
19     if(x[p])cnt--;
20     puts(cnt?"No":"Yes");
21     for(int i=1,a,b,p1,p2;i<=q;++i){
22         a=read(),b=read();
23         p1=a%k;p2=(a+1)%k;
24         if(p1!=p&&x[p1])cnt--;
25         if(p2!=p&&x[p2])cnt--;
26         x[p1]+=b;x[p2]-=b;
27         if(p1!=p&&x[p1])cnt++;
28         if(p2!=p&&x[p2])cnt++;
29         puts(cnt?"No":"Yes");
30     }
31 }
View Code

 

T3:射手座之日

我復雜度是錯的,極端情況下是$O(\frac{n^2}{k})$,其中k是一個基於數據的常數

具體范圍我也不知道,我只知道$4 \leq k  \leq n$

但是可以優化到穩定的$O(nlogn)$,常數會很大,和B哥一樣。

看特殊性質部分分,a序列就是dfs序。

那么問題就是對於每一個子區間[l,r]找到最大的p滿足$dfn[p]<=l$且$r<=dfr[p]$

其中$dfn/dfr$表示p子樹的dfs序區間。

而“最大這個限制不好處理,我們把權值做一遍樹上差分,這樣的話問題就轉化成了:對於每一個子區間[l,r]找到所有的p滿足$dfn[p]<=l$且$r<=dfr[p]$

枚舉p,它的控制區間內的所有子區間都滿足條件,那么答案就是

$\sum\limits_{i=1}^{n} \frac{y[i] \times (dfr[i]-dfn[i]+1) \times (dfr[i]-dfn[i]+2)}{2}$

其中$y$就是$x$數組在樹上差分之后的數組,即$y[i]=x[i]-x[f_i]$

而沒有了特殊性質之后怎么做?

外層還是枚舉p的話,內層的式子就不一樣了,是滿足上面條件的子區間數。

其實不考慮有包含關系的子區間,那么答案就是$y[i] \times \sum \frac{(r-l+1)\times(r-l+2)}{2}$

問題在於求出所有極長子區間。(極長是指不被包含的區間,如[l,r]存在時[l,r-1]不可能存在,而[1,4][7,9]可以共存)

把問題帶到樹上,考慮一個葉子節點,它的合法區間就是一個點。

其實對於每一個點它最開始的合法區間都是自己那一個點,后面還要合並上子樹內的所有點。

考慮怎么合並。

因為a是一個排列,所以這些區間當然不會有交集,那么我們可以用一個類似與歸並排序的過程來合並區間。

合並的過程中如果遇到$[L,p]+[p+1,R]$這樣的兩個區間,那么就把它合並成一個。

在回溯的同時統計$vector$里面的所有極長區間累加答案即可。

當然這個復雜度不對,雖然也不是很好卡(出題人想不到有這種打法)

然而正解的一種是不再用$vector$歸並,而是直接用樹上線段樹啟發式合並來維護極長區間。

時間復雜度是$O(nlogn)$的。

因為LNC說我數據結構必掛所以考場上還真的沒有打數據結構2333

 1 //remember to submit
 2 #include<cstdio>
 3 #include<vector>
 4 #include<algorithm>
 5 using namespace std;
 6 vector<int>L[200005],R[200005],reL,reR;
 7 int ec,fir[200005],l[200005],to[200005],x[200005],y[200005],dfn[200005],dfr[200005];
 8 int a[200005],tim,n,pos[200005];long long ans;
 9 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
10 void dfs(int p,int fa){
11     y[p]=x[p]-x[fa]; dfn[p]=++tim;
12     for(int i=fir[p];i;i=l[i])if(to[i]!=fa)dfs(to[i],p);
13     dfr[p]=tim;
14 }
15 void pushin(int l,int r){
16     if(reL.empty()||reR[reR.size()-1]!=l-1)return reL.push_back(l),reR.push_back(r),(void)0;
17     reR[reR.size()-1]=r;
18 }
19 void DFS(int p,int fa){
20     L[p].push_back(pos[dfn[p]]);R[p].push_back(pos[dfn[p]]);
21     for(int i=fir[p];i;i=l[i])if(to[i]!=fa){
22         DFS(to[i],p);
23         int p1=0,p2=0,e1=L[p].size(),e2=L[to[i]].size();
24         while(p1<e1&&p2<e2)if(L[p][p1]<L[to[i]][p2])pushin(L[p][p1],R[p][p1]),p1++;
25             else pushin(L[to[i]][p2],R[to[i]][p2]),p2++;
26         while(p1<e1)pushin(L[p][p1],R[p][p1]),p1++;
27         while(p2<e2)pushin(L[to[i]][p2],R[to[i]][p2]),p2++;
28         swap(reL,L[p]);swap(reR,R[p]);
29         reL.clear();reR.clear();L[to[i]].clear();R[to[i]].clear();
30     }int sz=L[p].size();
31     for(int i=0;i<sz;++i)ans+=(R[p][i]-L[p][i]+1ll)*(R[p][i]-L[p][i]+2ll)/2*y[p];
32 }
33 int main(){
34     freopen("sagittarius.in","r",stdin);
35     freopen("sagittarius.out","w",stdout);
36     scanf("%d",&n);
37     for(int i=2,f;i<=n;++i)scanf("%d",&f),link(f,i);
38     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
39     for(int i=1;i<=n;++i)scanf("%d",&x[i]);
40     dfs(1,0);
41     for(int i=1;i<=n;++i)a[i]=dfn[a[i]],pos[a[i]]=i;
42     DFS(1,0);
43     printf("%lld\n",ans);
44 }
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM