20180611小测

T1:

注意下面的那个求平均值的公式少了一个除大小,自行补上。
这种数据范围的最小方差生成树?真的可做?
BZOJ3754那题我可是n^2k暴力卡过去的啊......(好像只能暴力QAQ)
正解?标算好像就是求尽可能近的区间生成树。显然不对啊......
不可做,不可做。咕咕咕了。

T2:

怎么又是原题?
真不是BZOJ3505吗?
考虑枚举所有选三个点的方案再减去三点共线的。
就是C(n*m,3)-m*C(n,3)-n*C(m,3)-2*sigma(i from 1 to n-1,j from 1 to m-1)(gcd(i,j)-1)(n-i)(m-j)。
也就是全部的方案数为C(n*m,3),平行于坐标轴三点共线的有m*C(n,3)-n*C(m,3)种,斜向三点共线的,考虑枚举两边的两个点形成的向量,这样的向量存在(n-i)(m-j)个,对于每个向量,把中间点放置在格点上的方案有gcd(i,j)-1种,因为左右两种方向所以要全部*2。
但是,数据范围什么鬼......
考虑对公式进行数学变形:

右边的东西就很容易求和了(具体数学告诉你这样交换求和变量是对的):

对于gcd反演的惯例反演就是变成phi啦(什么这步你推不出来?丢人!退役吧!)

(不要吐槽我的公式渲染,msword2016在linux下就是这个德行)
由于求和式子的取值至于(n-1)/t和(m-1)/t有关,数论分块就很显然了。
然而卡常只有90分......
代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define debug cout
 6 typedef long long int lli;
 7 using namespace std;
 8 const int maxn=3e6+1e2,lim=3e6;
 9 const int mod=1e9+7,inv[]={0,1,500000004,333333336};
10 
11 inline lli C3(lli x) {
12     lli ret = 1; x %= mod;
13     for(int i=0;i<3;i++) ret = ret * ( x - i + mod ) % mod , ret = ret * inv[i+1] % mod;
14     return ret;
15 }
16 inline lli LSU(lli x) {
17     return x * ( x + 1 ) % mod * inv[2] % mod;
18 }
19 
20 lli phi[maxn],phix[maxn],phixx[maxn];
21 int n,m;
22 
23 inline void sieve() {
24     static int prime[maxn],cnt;
25     static bool vis[maxn];
26     phi[1] = 1;
27     for(int i=2;i<=lim;i++) {
28         if( !vis[i] ) prime[++cnt] = i , phi[i] = i - 1;
29         for(int j=1;j<=cnt&&(lli)i*prime[j]<=lim;j++) {
30             const int tar = i * prime[j];
31             vis[tar] = 1;
32             if( i % prime[j] ) phi[tar] = phi[i] * ( prime[j] - 1 );
33             else { phi[tar] = phi[i] * prime[j]; break; }
34         }
35     }
36     for(int i=1;i<=lim;i++) {
37         phix[i] = phi[i] * i % mod , phixx[i] = phix[i] * i % mod;
38         phi[i] = ( phi[i] + phi[i-1] ) % mod , phix[i] = ( phix[i] + phix[i-1] ) % mod , phixx[i] = ( phixx[i] + phixx[i-1] ) % mod;
39     };
40 }
41 
42 inline lli initans() {
43     lli ret = ( ( C3((lli)n*m) - n * C3(m) - m * C3(n) ) % mod + mod ) % mod;
44     ret = ( ret + LSU(n-1) * LSU(m-1) % mod * 2 % mod ) % mod;
45     return ret;
46 }
47 inline lli getsub() { // assert n <= m .
48     lli ret = 0;
49     if( n > m ) swap(n,m);
50     for(int i=1,j;i<n;i=j+1) {
51         j = min( ( n - 1 ) / ( ( n - 1 ) / i ) , ( m - 1 ) / ( ( m - 1 ) / i ) );
52         const lli apn = ( n - 1 ) / i , apm = ( m - 1 ) / i;
53         ret += ( phi[j] - phi[i-1] + mod ) % mod * apn % mod * apm % mod * n % mod * m % mod , ret %= mod;
54         ret += ( phixx[j] - phixx[i-1] + mod ) % mod * LSU(apn) % mod * LSU(apm) % mod , ret %= mod;
55         ret -= ( phix[j] - phix[i-1] + mod ) % mod * LSU(apn) % mod * apm % mod * m % mod , ret = ( ret + mod ) % mod;
56         ret -= ( phix[j] - phix[i-1] + mod ) % mod * LSU(apm) % mod * apn % mod * n % mod , ret = ( ret + mod ) % mod;
57     }
58     ret = ret * 2 % mod;
59     return ret;
60 }
61 
62 int main() {
63     sieve();
64     while( scanf("%d%d",&n,&m) == 2 && ( n || m ) ) n++ , m++ , printf("%lld\n",(initans()-getsub()+mod)%mod);
65 }
View Code

 


T3:

这题什么东西啊?真的可做?
写了一个三分套(线段树+RMQ+三分套二分)(什么鬼),发现不符合单调性,就能过样例,对拍拍一组WA一组。
无奈写了个O(n^2logn)的暴力,放进去交了,骗了20分......
正解是这个样子的:

(表示您并没有告诉我数据随机)
但是,如果数据真的随机,并没有那么麻烦!
我可以写一个O(n^2)暴力,从右向左枚举左端点,然后从左向右枚举右端点,对于每个右端点,我么令sj表示当前左端点到j的区间的最小和。显然每次更新的时候sj=min(sj,sj-1,ai-aj),于是就去掉log了。
这样暴力显然不能AC,我们能加入剪枝,如果当前sj*(n-i)已经<=答案了,我们就可以把内层循环break掉了。
然后就能AC啦!

考场20分代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<set>
  6 #define debug cout
  7 typedef long long int lli;
  8 using namespace std;
  9 const int maxn=1e5+1e2,lim=1e5;
 10 const int inf=0x3f3f3f3f , minf = -inf;
 11 const lli lli_inf = 0x3f3f3f3f3f3f3f3fll;
 12 
 13 int in[maxn],n,k;
 14 
 15 namespace Force {
 16     const int maxn=2e3+1e2;
 17     int f[maxn][maxn];
 18     multiset<int> ms;
 19     inline void work() {
 20         lli ans = -lli_inf;
 21         for(int i=1;i<=n;i++) {
 22             ms.clear() , ms.insert(in[i]) , f[i][i] = inf;
 23             for(int j=i+1;j<=n;j++) {
 24                 f[i][j] = f[i][j-1];
 25                 if( ms.find(in[j]) != ms.end() ) { f[i][j] = 0; continue; }
 26                 multiset<int>::iterator it = ms.lower_bound(in[j]);
 27                 if( it != ms.end() ) f[i][j] = min( f[i][j] , *it - in[j] );
 28                 if( it != ms.begin() ) f[i][j] = min( f[i][j] , in[j] - *--it );
 29                 if( j - i + 1 >= k ) ans = max( ans , (lli) f[i][j] * ( j - i ) );
 30                 ms.insert(in[j]);
 31             }
 32         }
 33         printf("%lld\n",ans);
 34     }
 35 }
 36 namespace Sol {
 37     int Log[maxn],mxl;
 38 
 39     struct RMQ_Min {
 40         int dat[maxn][20];
 41         int& operator [] (const int &x) { return *dat[x]; }
 42         inline void rebuild() {
 43             for(int j=1;j<=mxl;j++) for(int i=1;i<=n;i++) dat[i][j] = min( dat[i][j-1] , dat[i+(1<<(j-1))][j-1] );
 44         }
 45         inline int query(int l,int r) {
 46             int L = Log[r-l+1];
 47             return min( dat[l][L] , dat[r-(1<<L)+1][L] );
 48         }
 49     }rmqmi;
 50 
 51     struct RMQ_Max {
 52         int dat[maxn][20];
 53         int& operator [] (const int &x) { return *dat[x]; }
 54         inline void rebuild() {
 55             for(int j=1;j<=mxl;j++) for(int i=1;i<=n;i++) dat[i][j] = max( dat[i][j-1] , dat[i+(1<<(j-1))][j-1] );
 56         }
 57         inline int query(int l,int r) {
 58             int L = Log[r-l+1];
 59             return max( dat[l][L] , dat[r-(1<<L)+1][L] );
 60         }
 61     }rmqmx;
 62 
 63     struct SemgnetTree_Min {
 64         int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3],dat[maxn<<3],cnt;
 65         inline void build(int pos,int ll,int rr) {
 66             l[pos] = ll , r[pos] = rr , dat[pos] = inf;
 67             if( ll == rr ) return;
 68             const int mid = ( ll + rr ) >> 1;
 69             build(lson[pos]=++cnt,ll,mid) , build(rson[pos]=++cnt,mid+1,rr);
 70         }
 71         inline void update(int pos,const int &tar,const int &x) {
 72             if( l[pos] == r[pos] ) return void( dat[pos] = x );
 73             const int mid = ( l[pos] + r[pos] ) >> 1;
 74             tar <= mid ? update(lson[pos],tar,x) : update(rson[pos],tar,x) , dat[pos] = min( dat[lson[pos]] , dat[rson[pos]] );
 75         }
 76         inline int query(int pos,const int &ll,const int &rr) {
 77             if( ll <= l[pos] && r[pos] <= rr ) return dat[pos];
 78             const int mid = ( l[pos] + r[pos] ) >> 1;
 79             if( rr <= mid ) return query(lson[pos],ll,rr);
 80             else if( ll > mid ) return query(rson[pos],ll,rr);
 81             return min( query(lson[pos],ll,rr) , query(rson[pos],ll,rr) );
 82         }
 83         inline void reset() { cnt = 1; }
 84     }sgtmi;
 85 
 86     struct SemgnetTree_Max {
 87         int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3],dat[maxn<<3],cnt;
 88         inline void build(int pos,int ll,int rr) {
 89             l[pos] = ll , r[pos] = rr , dat[pos] = minf;
 90             if( ll == rr ) return;
 91             const int mid = ( ll + rr ) >> 1;
 92             build(lson[pos]=++cnt,ll,mid) , build(rson[pos]=++cnt,mid+1,rr);
 93         }
 94         inline void update(int pos,const int &tar,const int &x) {
 95             if( l[pos] == r[pos] ) return void( dat[pos] = x );
 96             const int mid = ( l[pos] + r[pos] ) >> 1;
 97             tar <= mid ? update(lson[pos],tar,x) : update(rson[pos],tar,x) , dat[pos] = max( dat[lson[pos]] , dat[rson[pos]] );
 98         }
 99         inline int query(int pos,const int &ll,const int &rr) {
100             if( ll <= l[pos] && r[pos] <= rr ) return dat[pos];
101             const int mid = ( l[pos] + r[pos] ) >> 1;
102             if( rr <= mid ) return query(lson[pos],ll,rr);
103             else if( ll > mid ) return query(rson[pos],ll,rr);
104             return max( query(lson[pos],ll,rr) , query(rson[pos],ll,rr) );
105         }
106         inline void reset() { cnt = 1; }
107     }sgtmx;
108 
109     int liml[maxn],limr[maxn];
110 
111     inline bool judge(int l,int r) {
112         int ll = rmqmx.query(l,r) , rr = rmqmi.query(l,r);
113         return ll <= l && r <= rr;
114     }
115     inline int binrit(int curl,int l,int r) {
116         if( judge(curl,r) ) return r;
117         int mid;
118         while( r > l + 1 ) {
119             mid = ( l + r ) >> 1;
120             if( judge(curl,mid) ) l = mid;
121             else r = mid;
122         }
123         return l;
124     }
125     inline int triseg(int pos) { // if same move l .
126         int l = liml[pos] , r = pos , lmid , rmid , tpl;
127         int cl , cr , ret = -inf;
128         while( r > l + 2 ) {
129             lmid = ( l + l + r ) / 3 , rmid = ( l + r + r ) / 3;
130 
131             tpl = rmqmi.query(lmid,pos);
132             if( tpl < pos ) cl = -inf;
133             else cl = binrit(lmid,pos,limr[pos]) - lmid;
134 
135             tpl = rmqmi.query(rmid,pos);
136             if( tpl < pos ) cr = -inf;
137             else cr = binrit(rmid,pos,limr[pos]) - rmid;
138 
139             if( cl <= cr ) l = lmid;
140             else r = rmid;
141         }
142         for(int i=l;i<=r;i++) {
143             tpl = rmqmi.query(i,pos);
144             if( tpl < pos ) continue;
145             ret = max( ret , binrit(i,pos,limr[pos]) - i );
146         }
147         return ret;
148     }
149     inline int getmxseg(int lim) {
150         int ret = -inf;
151         sgtmi.reset() , sgtmi.build(1,1,1e5);
152         for(int i=n;i;i--) limr[i] = rmqmi[i] = min(sgtmi.query(1,in[i]-lim+1,in[i]+lim-1)-1,n) , sgtmi.update(1,in[i],i);
153         sgtmx.reset() , sgtmx.build(1,1,1e5);
154         for(int i=1;i<=n;i++) liml[i] = rmqmx[i] = max(sgtmx.query(1,in[i]-lim+1,in[i]+lim-1)+1,1) , sgtmx.update(1,in[i],i);
155         rmqmi.rebuild() , rmqmx.rebuild();
156         for(int i=1;i<=n;i++) {
157             ret = max( ret , triseg(i) );
158         }
159         return ret >= k ? ret : -inf;
160     }
161     inline lli tri1() { // WAWAWA
162         int l = 1 , r = lim , lmid , rmid;
163         lli cl , cr , ret = -lli_inf;
164         while( r > l + 2 ) {
165             lmid = ( l + l + r ) / 3 , rmid = ( l + r + r ) / 3;
166             cl = (lli) lmid * getmxseg(lmid) , cr = (lli) rmid * getmxseg(rmid);
167             if( cl <= cr ) l = lmid;
168             else r = rmid;
169         }
170         for(int i=l;i<=r;i++) ret = max( ret , (lli) i * getmxseg(i) );
171         return ret;
172     }
173     inline lli tri2() { // WAWAWA
174         int l = 1 , r = lim , lmid , rmid;
175         lli cl , cr , ret = -lli_inf;
176         while( r > l + 2 ) {
177             lmid = ( l + l + r ) / 3 , rmid = ( l + r + r ) / 3;
178             cl = (lli) lmid * getmxseg(lmid) , cr = (lli) rmid * getmxseg(rmid);
179             if( cl < cr ) l = lmid;
180             else r = rmid;
181         }
182         for(int i=l;i<=r;i++) ret = max( ret , (lli) i * getmxseg(i) );
183         return ret;
184     }
185 
186     inline void getlog() {
187         for(int i=2;i<=n;i++) Log[i] = Log[i>>1] + 1;
188         mxl = Log[n];
189     }
190 
191     inline void work() {
192         --k , getlog() , printf("%lld\n",max(tri1(),tri2()));
193     }
194 }
195 
196 int main() {
197     static int T;
198     scanf("%d",&T);
199     while(T--) {
200         scanf("%d%d",&n,&k);
201         for(int i=1;i<=n;i++) scanf("%d",in+i);
202         if( n <= 3e3 ) Force::work();
203         else Sol::work();
204     }
205     return 0;
206 }
View Code

正解代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cstdlib>
 6 #define debug cout
 7 typedef long long int lli;
 8 using namespace std;
 9 const int maxn=1e5+1e2,lim=1e5,blk=1e3;
10 const int inf=0x3f3f3f3f , minf = -inf;
11 const lli lli_inf = 0x3f3f3f3f3f3f3f3fll;
12 
13 int in[maxn],n,k;
14 
15 namespace Force {
16     int s[maxn];
17     inline void work() {
18         lli ans = -lli_inf;
19         memset(s,0x3f,sizeof(s));
20         for(int i=n;i;i--) {
21             for(int j=i+1;j<=n/*&&j<=i+blk*/;j++) {
22                 s[j] = min( s[j] , abs(in[i]-in[j]) ) , s[j] = min( s[j] , s[j-1] );
23                 if( j - i >= k )ans = max( ans , (lli) s[j] * ( j - i ) );
24                 if( (lli) s[j] * ( n - i ) <= ans ) break;
25             }
26         }
27         printf("%lld\n",ans);
28     }
29 }
30 
31 int main() {
32     static int T;
33     scanf("%d",&T);
34     while(T--) {
35         scanf("%d%d",&n,&k) , --k;
36         for(int i=1;i<=n;i++) scanf("%d",in+i);
37         Force::work();
38     }
39 }
View Code

 


这种题都做不出来,果然还是我太菜啦!
对了我决定把电脑里的Win10删掉以彻底杜绝自己想要推gal的思想

冷(つめ)たかった 寂(さみ)しかった
好冷啊,好寂寞
凍(い)てつく街(まち)に息衝(いきづ)く
生活在这冰封的城镇里
優(やさ)しい愛(あい)の唄(うた)が
温柔地爱的歌谣
胸(むね)の奥(おく)積(つ)もって
在心中回响
変わる景色 幼い私 隔てた 境界線(きょうかいせん
将变化的景色和幼小的自己分隔的境界线
見(み)えなくなるくらい 染(そ)めていたの
变得不再那样清晰

posted @ 2018-06-11 16:41  Cmd2001  阅读(332)  评论(0编辑  收藏  举报