四校联考比赛题解FJ NOIP 四校联考 2017 Round 7

Posted PinkRabbit

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四校联考比赛题解FJ NOIP 四校联考 2017 Round 7相关的知识,希望对你有一定的参考价值。

此次比赛为厦门一中出题。都是聚劳,不敢恭维。

莫名爆了个0,究其原因,竟然是快读炸了……很狗,很难受。

话不多说,来看看题:

【T1】

题意:

样例:

PS:1<=h[i]<=100000。

题解:

假设\\(max\\left(h_{i}\\right)=M\\),可以发现最大高度不超过\\(M+n\\)。

而用\\(m\\)块砖,向上最多能搭\\(\\sqrt{m}\\)个。

故最大高度为\\(M+min\\left(n,\\sqrt{m}\\right)\\)。

而最低高度为\\(M\\)(或\\(M+1\\))。

也就是说,高度的范围不超过3163。

而可以看出对于高度\\(h\\),能否搭建起高\\(h\\)的塔是单调的。

如果我们二分高度\\(h\\),计算能否搭建,就能够较快出解。

考虑在第\\(i\\)列搭上\\(h\\)的高度,那么最少需要多少砖块呢?

当然是按照金字塔形斜向下,直到遇到第一个可以作为支撑的砖块。

设\\(left\\left[i\\right]\\left[h\\right]\\)为坐标\\(\\left(i,h\\right)\\)向左斜向下遇到的第一个砖块的标号,\\(right\\left[i\\right]\\left[h\\right]\\)则为向右斜向下,若不存在,则值为0。

那么最少需要的砖块数(包括已经搭建的)等于:

\\(Sum[i][h]=h(right[i][h]-left[i][h]-1)-\\frac{(i-left[i][h])(i-left[i][h]-1)}{2}-\\frac{(right[i][h]-i)(right[i][h]-i-1)}{2}\\)。

而需要多搭的为:\\(Sum[i][h]-(sum_{right[i][h]-1}-sum_{left[i][h]})\\),其中\\(sum\\)为前缀和。

现在,如何快速算出\\(left\\)和\\(right\\)呢?

看往左斜向下的,容易发现,\\(k\\)能够阻挡\\((i,h)\\)当且仅当\\(h_{k}-k\\geqslant h-i\\)。

而对于向右下方的,我们有,\\(k\\)能够阻挡\\((i,h)\\)当且仅当\\(h_{k}+k\\geqslant h+i\\)。

考虑记录下\\(L_{k}=h_{k}-k\\)与\\(R_{k}=h_{k}+k\\)。

那么我们就是对特定\\(i,h\\)要求出从右往左第一个\\(k\\)使得\\(L_{k}\\geqslant h-i\\),求出从左往右第一个\\(k\\)使得\\(R_{k}\\geqslant h+i\\)。

这是单调栈的模型,先把\\(L_{k}\\)和\\(R_{k}\\)用单调栈维护一遍。

而在计算过程中,\\(h+i\\)与\\(h-i\\)是单调递增或递减的,这有了双指针扫描的可能性。

这就是整体思路,代码有点复杂……

 1 #include<cstdio>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 #define dF(i,a,b) for(int i=a;i>=b;--i)
 4 int n,m,h[100005],Ans,M;
 5 long long sum[100005];
 6 int left[100005][2],lp,right[100005][2],rp;
 7 int L[100005],R[100005];
 8 inline int Max(int x,int y){return x>y?x:y;}
 9 void init(){
10     scanf("%d%d",&n,&m);
11     F(i,1,n) scanf("%d",h+i), M=Max(M,h[i]);
12     F(i,1,n) sum[i]=sum[i-1]+h[i];
13     lp=0;
14     F(i,1,n){
15         while(lp&&left[lp][0]<=h[i]-i) --lp;
16         left[++lp][0]=h[i]-i;
17         left[lp][1]=i;
18     } left[0][0]=99999999;
19     rp=0;
20     dF(i,n,1){
21         while(rp&&right[rp][0]<=h[i]+i) --rp;
22         right[++rp][0]=h[i]+i;
23         right[rp][1]=i;
24     } right[0][0]=99999999;
25 //    F(i,1,lp) printf("(%d,%d) ",left[i][0],left[i][1]); puts("");
26 //    F(i,1,rp) printf("(%d,%d) ",right[i][0],right[i][1]); puts("");
27     Ans=M;
28 }
29 int main(){
30     freopen("block.in","r",stdin);
31     freopen("block.out","w",stdout);
32     init();
33     int l=M+1, r=M+40000, mid, ok;
34     while(l<=r){
35         mid=(l+r)>>1;
36         ok=0;
37 //        printf("%d:\\n",mid);
38         for(int i=1,pos=1;i<=n;++i){
39             L[i]=0;
40             if(pos!=lp&&left[pos+1][0]>=mid-i) ++pos;
41             if(left[pos][0]>=mid-i) L[i]=left[pos][1]+1;
42         }
43 //        for(int i=1;i<=n;++i) printf("%d ",L[i]); puts("");
44         for(int i=n,pos=1;i>=1;--i){
45             R[i]=0;
46             if(pos&&right[pos+1][0]>=mid+i) ++pos;
47             if(right[pos][0]>=mid+i) R[i]=right[pos][1]-1;
48         }
49 //        for(int i=1;i<=n;++i) printf("%d ",R[i]); puts("");
50         F(i,1,n){
51             if(L[i]==0||R[i]==0) continue;
52             long long Sum=
53             (long long)mid*(R[i]-L[i]+1)-
54             (long long)(i-L[i]+1)*(i-L[i])/2-
55             (long long)(R[i]-i+1)*(R[i]-i)/2-
56             (sum[R[i]]-sum[L[i]-1]);
57 //            printf("%d:%lld ",i,Sum);
58             if(Sum<=m) {ok=1; break;}
59         }//puts("");
60         if(ok) l=mid+1, Ans=mid;
61         else r=mid-1;
62     }
63     printf("%d",Ans);
64     return 0;
65 }

【T2】

题意:

样例:

题解:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cassert>
 5 using namespace std;
 6 #define rep(i,a,n) for (int i=a;i<n;i++)
 7 #define per(i,a,n) for (int i=n-1;i>=a;i--)
 8 typedef long long ll;
 9 // head
10 
11 const int N=2501000;
12 int n,m,cnt0[N],cnt1[N];
13 ll m0,md,cnt2[N];
14 int main() {
15     freopen("cake.in","r",stdin);
16     freopen("cake.out","w",stdout);
17     scanf("%d%d",&m,&n);
18     scanf("%lld%lld",&m0,&md);
19     rep(i,1,m+1) {
20 //        printf("%lld\\n",m0);
21         cnt0[m0]++;
22         m0=(m0*58+md)%(n+1);
23     }
24 //    puts("");
25     scanf("%lld%lld",&m0,&md);
26     rep(i,1,n+1) {
27 //        printf("%lld\\n",m0);
28         cnt1[m0]++; cnt2[m0]+=m0;
29         m0=(m0*58+md)%(m+1);
30     }
31     int x=0; ll sx=0;
32     rep(i,1,m+1) cnt1[i]+=cnt1[i-1],cnt2[i]+=cnt2[i-1];
33     ll ans=cnt2[m];
34 //    puts("");
35     rep(i,0,n+1) {
36         rep(j,0,cnt0[i]) {
37             x++; sx+=i;
38             int y=cnt1[m-x];
39             assert(x<=m&&y<=n);
40             ll ret=(ll)(m-x)*(n-y)+cnt2[m-x]+sx;
41 //            printf("%lld\\n",ret);
42             ans=min(ans,ret);
43         }
44     }
45     printf("%lld\\n",ans);
46 }

【T3】

题意:

题解:

我个人不会做……有待学习。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #define rep(i,a,b) for(int i=(a);i<=(b);i++)
  6 #define per(i,a,b) for(int i=(a);i>=(b);i--)
  7 #define Rep(i,x) for(int i=head[x];i+1;i=nxt[i])
  8 #define pb push_back
  9 #include<algorithm>
 10 using namespace std;
 11 typedef long long ll;
 12 const int N=4e6+5;
 13 const int M=8e6+5;
 14 inline void read(int &x){x=0;char ch=getchar(); while(ch<\'0\') ch=getchar(); while(ch>=\'0\'){x=x*10+ch-48;ch=getchar();}}
 15 inline void judge()
 16 {
 17     freopen("tree.in","r",stdin);
 18     freopen("tree.out","w",stdout);
 19 }
 20 int fa[N],head[N],nxt[M],to[M],e,w[M],id[M];
 21 int wod[N];
 22 int son[N][2],pd[N],tp[N];
 23 inline void init(){memset(head,-1,sizeof(head)); e=0;}
 24 inline void add_edge(int x,int y,int z,int ii){to[e]=y;w[e]=z;nxt[e]=head[x];id[e]=ii;head[x]=e++;}
 25 ll ma[N][2],ans[N][2];
 26 inline void Insert(int x,ll y,int cjl,int ii)
 27 {
 28     if(ma[x][0]<y){ma[x][1]=ma[x][0];ma[x][0]=y;son[x][1]=son[x][0];son[x][0]=cjl;pd[x]=ii;}
 29     else if(y>ma[x][1]){ma[x][1]=y;son[x][1]=cjl;}
 30 }
 31 void dfs(int x)
 32 {
 33     ma[x][0]=ma[x][1]=0;Rep(i,x)
 34     {
 35         int j=to[i]; if(j==fa[x]) continue; fa[j]=x; tp[j]=id[i];
 36         dfs(j); Insert(x,ma[j][0]+(ll)w[i],j,tp[j]);
 37     }
 38 }
 39 inline void Insert3(int x,ll y)
 40 {
 41     if(ma[x][0]<y){ma[x][1]=ma[x][0];ma[x][0]=y;}
 42     else if(y>ma[x][1])ma[x][1]=y;
 43 }
 44 void dfs3(int x,int f,int pp)
 45 {
 46     ma[x][0]=ma[x][1]=0;ans[pp][0]=0;Rep(i,x)
 47     {
 48         int j=to[i]; if(j==f) continue;
 49         dfs3(j,x,id[i]); Insert3(x,ma[j][0]+(ll)w[i]);
 50         ans[pp][0]=max(ans[pp][0],ans[id[i]][0]);
 51     }ans[pp][0]=max(ans[pp][0],ma[x][0]+ma[x][1]);
 52 }
 53 vector<int> tt,Route,Rid,tt2;
 54 void dfs2(int x)
 55 {
 56     tt.push_back(x); if(pd[x])tt2.push_back(pd[x]);
 57     if(son[x][0]) dfs2(son[x][0]);
 58     else return;
 59 }
 60 ll md[N];
 61 int main()
 62 {
 63     judge();
 64     int n;read(n);init();rep(i,1,n-1)
 65     {
 66         int x,y,z;read(x);read(y);read(z);
 67         add_edge(x,y,z,i);add_edge(y,x,z,i);
 68         wod[i]=z;
 69     }fa[1]=0;dfs(1);int mj=1;rep(i,2,n) if(ma[i][0]+ma[i][1]>ma[mj][0]+ma[mj][1]) mj=i;
 70     rep(i,1,n-1) ans[i][1]=ma[mj][0]+ma[mj][1];
 71     if(son[mj][0])
 72     {
 73         dfs2(son[mj][0]); for(int i=(int)tt.size()-1;i>=0;i--) Route.pb(tt[i]);
 74         for(int i=(int)tt2.size()-1;i>=0;i--) Rid.pb(tt2[i]); tt2.clear();tt.clear();
 75         Rid.pb(tp[son[mj][0]]);
 76     }
 77     Route.pb(mj);
 78     if(son[mj][1])
 79     {
 80         Rid.pb(tp[son[mj][1]]);
 81         dfs2(son[mj][1]); for(int i=0;i<(int)tt.size();i++) Route.pb(tt[i]);
 82         for(int i=0;i<(int)tt2.size();i++) Rid.pb(tt2[i]);
 83     }
 84     int sz=Route.size();memset(ma,0,sizeof(ma));
 85     ll pre=0;ll maa=0;
 86     rep(i,0,sz-1)
 87     {
 88         int j=Route[i];
 89         Rep(xjt,j)
 90         {
 91             if(i && to[xjt]==Route[i-1]) continue;
 92             if(i<sz-1 && to[xjt]==Route[i+1]) continue;
 93             dfs3(to[xjt],j,id[xjt]); md[i]=max(md[i],w[xjt]+ma[to[xjt]][0]);
 94         }
 95         maa=max(maa,md[i]+pre);if(i!=sz-1)ans[Rid[i]][0]=maa;
 96         if(i!=sz-1) pre+=wod[Rid[i]];
 97     }
 98     pre=0; maa=0;memset(md,0,sizeof(md));
 99     per(i,sz-1,0)
100     {
101         int j=Route[i];
102         Rep(xjt,j)
103         {
104             if(i && to[xjt]==Route[i-1]) continue;
105             if(i<sz-1 && to[xjt]==Route[i+1]) continue;
106             dfs3(to[xjt],j,id[xjt]); md[i]=max(md[i],w[xjt]+ma[to[xjt]][0]);
107         }
108         maa=max(maa,md[i]+pre);if(i)ans[Rid[i-1]][1]=maa;
109         if(i) pre+=wod[Rid[i-1]];
110     }
111     rep(i,1,n-1) if(ans[i][0]>ans[i][1]) swap(ans[i][0],ans[i][1]);
112     ll solo=0;
113     rep(i,1,n-1)
114     {
115         solo+=ans[i][1]*23333ll+ans[i][0]*2333ll+233ll*(ll)i*(ll)i+23ll*(ll)i+2ll;
116         //cerr<<ans[i][1]<<\' \'<<ans[i][0]<<endl; 
117         solo%=2333333333333333ll;
118     }
119     printf("%lld\\n",solo);
120     return 0;
121 }

 

以上是关于四校联考比赛题解FJ NOIP 四校联考 2017 Round 7的主要内容,如果未能解决你的问题,请参考以下文章

2017 10 01国庆节大礼包 四校联考

20171001四校联考

2017-2-26福建四校联考

2017-2-19四校联考

9月25日四校联考

2017-2-26四校联考