[机房测试]11.7
连续两天低级错误送分,本来考的分就不多,直接送下300了。
%骆神600吊打std
欢迎转载ssw02的博客:https://www.cnblogs.com/ssw02/p/11814079.html
你相信引力吗
不,我不相信
读入
一个数N表示环的长度 , 然后N个数表示
思路
30分做法,提供一个N^2的思路。
考虑破环为链,把链复制接在后面,只靠虑一个点向后所能得到的贡献。这个可以N^2记录重边,很好写。
满分做法:考虑到破环时,不如把最大的点作为起点断开环,这样可以保证没有跨过这个环的贡献值。这个东西开个栈就可以维护。
同时考虑到有可能端点和序列的另一端(毕竟是环)的贡献,这种贡献只有不断倒叙得到最大值才可以得到,逆序循环一遍即可。
#include<bits/stdc++.h>
using namespace std ;
#define ll long long
const int MAXN = 5000005 ;
inline int read(){
int s=0 ; char g=getchar() ; while( g>'9'||g<'0')g=getchar() ;
while( g>='0'&&g<='9')s=s*10+g-'0',g=getchar() ; return s ;
}
int N , a[MAXN*2] , b[MAXN] , st[MAXN] , num[MAXN] ;
bool vis[705][705] , used[MAXN] ;
void work1(){
int tot1 = 0 ;
for( int i = 1 ; i <= N ; ++i ){
int maxx = 0 ;
for( int j = i+1 ; j < i+N ; ++j ){
if( maxx <= a[j] && maxx <= a[i] ){
int k = j ;
if( k > N ) k -= N ; if( vis[i][k] )continue ;
tot1++ ; vis[i][k] = vis[k][i] = true ;
}
maxx = max( maxx , a[j] ) ;
}
}
cout<<tot1 ;
}
void work2(){
int maxx = 0 , pos = 0 , top = 0 ;
for( int i = 1 ; i <= N ; ++i )
if( a[i] > maxx )maxx=a[i],pos=i ;
for( int i = 1 , j = pos ; i <= N ; ++i , ++j ){
if( j > N ) j-=N ; b[i]=a[j] ;//断环为链
}
ll ans = 0 ;
for( int i = 1 ; i <= N ; ++i ){
while( top && st[top]<b[i] )ans += (ll)num[top--] ;
if( st[top] == b[i] )ans += (ll)num[top],num[top]++ ;
else st[++top] = b[i] , num[top] = 1 ;
if( top > 1 )ans++ ;
}
maxx = 0 , pos = 0 ;
for( int i = N ; i > 1 ; --i )
if( b[i] > maxx )ans++ , maxx = b[i] , pos = 1 ;
else if( b[i] == maxx )ans++ , pos++ ;
cout<<ans-pos ;
}
int main(){
freopen("jolyne.in","r",stdin) ;
freopen("jolyne.out","w",stdout) ;
N = read() ; int flag = true ;
for( register int i = 1 ; i <= N ; ++i ){
a[i] = a[i+N]= read() ;
if( i != 1 )if( a[i] != a[i-1] )flag = false ;
}
if( N <= 700 ){work1() ; return 0 ;}
if( flag ){cout<<(ll)N*(ll)(N-1)/2LL ;return 0;}
else work2() ;
}
停不下来的团长奥尔加
5分钟秒切题,为一的价值就是教会ssw02别忘了先+mod在取模。。。。
只要想到要通过一个点必须走这个点偶数次,借用一下汉诺塔的思想,sum[i]表示第一次走到i花费的时间。走过他就需要触发一次刺客伍六七。。回到pi,相当于你有回到了第一次来到pi的状态,在走到i就可以通过i了。
方程很简单 sum[i] = sum[i-1]*2-sum[p[i-1]]+2 , sum[1] = 0 , sum[N+1]为所求
#include<bits/stdc++.h>
using namespace std ;
const int MAXN = 1000005 , mod = 1e9+7 ;
inline int read(){
int s=0 ; char g=getchar() ; while( g>'9'||g<'0')g=getchar() ;
while( g>='0'&&g<='9')s=s*10+g-'0',g=getchar() ; return s ;
}
int sum[MAXN] , p[MAXN] , N ;//还没我快读长。。。。。
int main(){
freopen("rideon.in","r",stdin) ;
freopen("rideon.out","w",stdout) ;
N = read() ;
for( register int i = 1 ; i <= N ; ++i )p[i] = read() ; sum[1] = 0 ;
for( register int i = 2 ; i <= N+1 ; ++i ){
sum[i] = ( (2*sum[i-1]-sum[p[i-1]]+2)%mod+mod )%mod ;
}
cout<<sum[N+1] ;
}
Lesson5!
好题,ssw02也讲不太清楚,两种方法只做了一种,做完堆做法在放(ssw02好久没写过堆了)
代码
总结
ssw02蠢了。。
T1读题花了50分钟还没读懂(不是ssw02语文菜,而是出题人没有给样例解释。。。算了还是ssw02菜),做法一来就想复制两倍,这个惯性思维有问题。
T2 : 5分钟切完,10分钟测完极限数据(为何ssw02搓的极限数据刚好没报负啊!!!)
T3 : 暴力topo可以写55分,正解是BZOJ3828原题。