[机房测试]11.7

[机房测试]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原题。

posted @ 2019-11-07 18:21  蓝银杏-SSW  阅读(216)  评论(4编辑  收藏  举报
//结束