1. 程式人生 > >“玲瓏杯”算法比賽 Round #14題目與標程

“玲瓏杯”算法比賽 Round #14題目與標程

swap const 如果 成了 isa code 準備 為什麽 bottom

“玲瓏杯”算法比賽 Round #14By:wxh010910

Start Time:2017-05-13 16:00:00 End Time:2017-05-13 18:30:00 Refresh Time:2017-05-20 09:51:24 Public

玲瓏OJ比賽提交地址:http://www.ifrog.cc/acm/contest/1016

Round#14題解:http://www.ifrog.cc/acm/solution/19

A -- No Game No Life

Time Limit:1s Memory Limit:256MByte

Submissions:473Solved:226

DESCRIPTION

一對叫做 的兄妹玩遊戲特別厲害,組隊吊打所有人,

但是現實世界對他們很不友好,所以他們就去了異世界,

那個異世界有16個種族,不能打仗,只能玩遊戲。

有一次他們和數據結構種族的人比賽,看誰寫數據結構寫得快,這時候出現了這樣一道題:技術分享

給一個序列a,每次兩個操作。

1、把所有數字x變成y2、詢問序列一個位置上面的值

INPUT第一行兩個數n,m第二行n個數表示a序列後面有m行,每行格式為1 x y或者2 x分別表示把所有值為x的數變成y或者詢問序列上x位置的數值OUTPUT對於每個2操作,即詢問,輸出一個數表示答案SAMPLE INPUT5 55 5 5 5 52 31 5 22 31 8 32 1SAMPLE OUTPUT522HINTn,m <= 1000, a[i] <= 1000000000你作為妹妹當然要AC掉這題啦SOLUTION“玲瓏杯”ACM比賽 Round #14

標程:

#include <bits/stdc++.h> #define MAXN 100010 using namespace std;  int n , m , a[ MAXN ]; map < int , int > wocaonimalegebia;  inline int read() { 	register int x = 0 , ch = getchar(); 	while( !isdigit( ch ) ) ch = getchar(); 	while( isdigit( ch ) ) x = x * 10 + ch - ‘0‘ , ch = getchar(); 	return x; }  int main() { 	n = read() , m = read(); 	for( register int i = 1 ; i <= n ; i++ ) a[i] = read() , wocaonimalegebia[ a[i] ] = a[i]; 	while( m-- ) 		if( read() == 1 ) 		{ 			int x = read(); 			wocaonimalegebia[x] = read(); 		} 		else printf( "%d\n" , wocaonimalegebia[ a[ read() ] ] ); 	return 0; }

B -- RE:從零開始的異世界生活

Time Limit:1s Memory Limit:256MByte

Submissions:368Solved:52

DESCRIPTION

486到了異世界,看到了一群可愛的妹子比如蕾姆啊,艾米莉亞啊,拉姆啊,白鯨啊,怠惰啊等等!
有一天膜女告訴486說她的能力可能不能再用了,因為膜女在思考一個數據結構題,沒心情管486了。
486說我來幫你做,膜女說你很棒棒哦!
技術分享

給一個集合,最開始為空(不是數學上的集合)
五個操作:

1、插入x
2、把小於x的數變成x
3、把大於x的數變成x
4、求集合中第x小數
5、求集合中小於x的數個數

INPUT第一行一個數m後面有m行,每行格式為opt x,opt表示是什麽操作,x表示操作的值OUTPUT對於每個4,5操作,輸出一個值表示答案SAMPLE INPUT51 11 34 12 334 1SAMPLE OUTPUT133HINTm <= 100000 , x <= 1000000000SOLUTION“玲瓏杯”ACM比賽 Round #14 標程:

#include <bits/stdc++.h> #define ratio 4 #define MAXN 1000010 #define merge( a , b ) new_Node( a -> size + b -> size , b -> value , a , b ) #define new_Node( s , v , a , b ) ( & ( * st[ cnt++ ] = Node( s , v , a , b ) ) ) #define update( cur ) if( cur -> left -> size ) cur -> size = cur -> left -> size + cur -> right -> size , cur -> value = cur -> right -> value;  using namespace std;  struct Node { 	int size , value; 	Node * left , * right; 	Node( int s , int v , Node * a , Node * b ) : size( s ) , value( v ) , left( a ) , right( b ) {} 	Node() {} } * root , * null , * st[300000] , t[300000];  int n , m , x , cnt;  int find( int x , Node * cur ) { 	if( !cur -> left -> size ) return cur -> value; 	return x > cur -> left -> size ? find( x - cur -> left -> size , cur -> right ) : find( x , cur -> left ); }  int zhentamashabibuyaoxiajibaqibianlaingminghaobuhaoa( int x , Node * cur ) { 	if( !cur -> left -> size ) return ( x > cur -> value ) * cur -> size; 	return x > cur -> left -> value ? zhentamashabibuyaoxiajibaqibianlaingminghaobuhaoa( x , cur -> right ) + cur -> left -> size : zhentamashabibuyaoxiajibaqibianlaingminghaobuhaoa( x , cur -> left ); }  void split( int x , Node * cur ) { 	if( x > cur -> left -> size ) split( x - cur -> left -> size , cur -> right ) , cur -> left = merge( cur -> left , cur -> right -> left ) , st[ --cnt ] = cur -> right , cur -> right = cur -> right -> right; 	else if( x < cur -> left -> size ) split( x , cur -> left ) , cur -> right = merge( cur -> left -> right , cur -> right ) , st[ --cnt ] = cur -> left , cur -> left = cur -> left -> left; }  void insert( int x , Node * cur ) { 	if( !cur -> left -> size ) 		if( cur -> value < x ) cur -> left = new_Node( cur -> size , cur -> value , null , null ) , cur -> right = new_Node( 1 , x , null , null ); 		else cur -> left = new_Node( 1 , x , null , null ) , cur -> right = new_Node( cur -> size , cur -> value , null , null ); 	else insert( x , x > cur -> left -> value ? cur -> right : cur -> left ); 	update( cur ); }  void dispose( Node * cur ) { 	if( cur -> left -> size ) st[ --cnt ] = cur -> left , st[ --cnt ] = cur -> right , dispose( cur -> left ) , dispose( cur -> right ); }  inline void low( int x ) { 	Node * cur = root; 	int s = zhentamashabibuyaoxiajibaqibianlaingminghaobuhaoa( x + 1 , cur ); 	if( s == 0 ); 	else if( s == cur -> size ) 		dispose( cur ) , * cur = Node( s , x , null , null ); 	else 		split( s , cur ) , dispose( cur -> left ) , * cur -> left = Node( s , x , null , null ); }  inline void up( int x ) { 	Node * cur = root; 	int s = zhentamashabibuyaoxiajibaqibianlaingminghaobuhaoa( x + 1 , cur ); 	if( s == 0 ) 		dispose( cur ) , * cur = Node( cur -> size , x , null , null ); 	else if( s == cur -> size ); 	else 		split( s , cur ) , dispose( cur -> right ) , * cur -> right = Node( cur -> size - s , x , null , null ); }  struct io { 	char ibuf[1 << 23] , * s , obuf[1 << 22] , * t; 	int a[24]; 	io() : t( obuf ) 	{ 		fread( s = ibuf , 1 , 1 << 23 , stdin ); 	} 	~io() 	{ 		fwrite( obuf , 1 , t - obuf , stdout ); 	} 	inline int read()  	{ 		register int u = 0; 		while( * s < 48 ) s++; 		while( * s > 32 ) 			u = u * 10 + * s++ - 48; 		return u; 	} 	template< class T > 	inline void print( register T u ) 	{ 		static int * q = a; 		if( !u ) * t++ = 48; 		else 		{ 			if( u < 0 ) 				* t++ = 45 , u *= -1; 			while( u ) * q++ = u % 10 + 48 , u /= 10; 			while( q != a ) 				* t++ = * --q; 		} 		* t++ = ‘\n‘; 	} } ip;  #define read ip.read #define print ip.print  int main() { 	m = read(); 	for( register int i = 0 ; i < 300000 ; i++ ) st[i] = & t[i]; 	null = new_Node( 0 , 0 , 0 , 0 ); 	while( m-- ) 	{ 		int opt = read(); 		if( opt == 1 ) 			if( root ) insert( read() , root ); 			else root = new_Node( 1 , read() , null , null ); 		else if( opt == 2 ) low( read() ); 		else if( opt == 3 ) up( read() ); 		else if( opt == 4 ) print( find( read() , root ) ); 		else print( zhentamashabibuyaoxiajibaqibianlaingminghaobuhaoa( read() , root ) ); 	} 	return 0; }

C -- Another

Time Limit:3s Memory Limit:256MByte

Submissions:230Solved:20

DESCRIPTION

因為奇怪的原因,主角榊原恒一轉學到了夜見山市,進入了3年3班,看到了一個非常可愛的妹子Misaki。
但是…為什麽其他同學都看不見Misaki呢?為什麽Misaki被叫做不存在的人呢?為什麽班上一直在死人呢?
為了搞清楚這件事情,主角去學習了OI,準備用圖靈測試看看妹子是不是AI(正常人不應該懷疑妹子是不是鬼嗎)
在NOIP day1T2,他遇到了一道數據結構題:
技術分享
給你一個樹,每個點有一個顏色,每種顏色有一個值t,定義一個點的跑步程度ans為:
設子樹中顏色為x的點有y個,如果y >= t[x] , ans++;
求所有點的跑步程度的和

INPUT第一行兩個數n,h,h表示顏色個數後面有n - 1行,每行一個數表示該點的父親後面有n行,表示每個點的顏色後面有h行,每行表示該顏色的tOUTPUT輸出一個值表示答案SAMPLE INPUT5 512341 2 3 4 511111SAMPLE OUTPUT15HINTn,m,h,t <= 100000若出現爆棧問題,改棧方法請參考1093題目代碼1093地址:http://www.ifrog.cc/acm/problem/1093代碼地址:http://ideone.com/Wk24ETSOLUTION“玲瓏杯”ACM比賽 Round #14

標程:

#define OPENSTACK #include <bits/stdc++.h> using namespace std; #define MAXN 500010  using namespace std;  int n , h , size[ MAXN ] , fa[ MAXN ] , dep[ MAXN ] , son[ MAXN ] , top[ MAXN ] , l[ MAXN ] , r[ MAXN ] , tag[ MAXN ] , tot , p[10000000] , cnt; vector < int > linker[ MAXN ] , wocaonimabi[ MAXN ]; long long ans;  inline int read() { 	int x = 0 , ch = getchar(); 	while( !isdigit( ch ) ) ch = getchar(); 	while( isdigit( ch ) ) x = x * 10 + ch - ‘0‘ , ch = getchar(); 	return x; }  #define cur linker[x][i]  void dfs1( int x ) { 	size[x] = 1; 	for( int i = 0 ; i < linker[x].size() ; i++ ) 		if( cur != fa[x] ) 		{ 			fa[ cur ] = x , dep[ cur ] = dep[x] + 1; 			dfs1( cur ) , size[x] += size[ cur ]; 			if( size[ cur ] > size[ son[x] ] ) son[x] = cur; 		} }  void dfs2(int x, int t) { 	top[x] = t; 	l[x] = ++tot; 	if (son[x] ) { 		dfs2( son[x] , t ); 	} 	for( int i = 0 ; i < linker[x].size() ; i++ ) 		if( cur != fa[x] && cur != son[x] ) 			dfs2( cur , cur ); }  inline void modify( int l , int r ) { 	tag[l]++ , tag[r + 1]--; 	p[ ++cnt ] = l , p[ ++cnt ] = r + 1; }  void modify( int x ) { 	while( x ) 	{ 		modify( l[ top[x] ] , l[x] ); 		x = fa[ top[x] ]; 	} }  inline void addedge(int x, int y) { 	linker[x].push_back( y ); }  int main() { 	#ifdef OPENSTACK 		int size = 128 << 20; // 64MB 		char *tangtangtangtanglaoshia = (char*)malloc(size) + size; 		#if (defined _WIN64) or (defined __unix) 			__asm__("movq %0, %%rsp\n" :: "r"(tangtangtangtanglaoshia)); 		#else 			__asm__("movl %0, %%esp\n" :: "r"(tangtangtangtanglaoshia)); 		#endif 	#endif 	n = read() , h = read(); 	for( int i = 2 ; i <= n ; i++ ) addedge( read() , i ); 	for( int i = 1 ; i <= n ; i++ ) wocaonimabi[ read() ].push_back( i ); 	dfs1( 1 ); 	dfs2( 1 , 1 ); 	for( int v = 1 ; v <= h ; v++ ) 	{ 		int t = read(); 		for(int i = 0 ; i < wocaonimabi[v].size() ; i++ ) 			modify( wocaonimabi[v][i] ); 		p[ ++cnt ] = 1 , p[ ++cnt ] = n + 1; 		sort( p + 1 , p + cnt + 1 ); 		cnt = unique( p + 1 , p + cnt + 1 ) - p; 		for(int i = 1 , last = 1 , now = 0 ; i <= cnt ; i++ ) 		{ 			if( now >= t ) ans += p[i] - last; 			now += tag[ p[i] ] , tag[ p[i] ] = 0; 			last = p[i]; 		} 		cnt = 0; 	} 	cout << ans << endl; 	#ifdef OPENSTACK 		exit(0); 	#else 		return 0; 	#endif }

D -- 輕拍翻轉小膜女

Time Limit:1s Memory Limit:256MByte

Submissions:36Solved:4

DESCRIPTION

可可娜是一個可愛的初中二年級妹子,本來在認真學習的她偶遇了膜法少女帕比卡,於是和她一起潛入稱為pure illusion的異世界,尋找“mimi的碎片”,據說找齊了所有碎片可以掌控pure illusion從而掌控世界。
但是…
這番其實講的是家庭倫理…
先不管這麽多,有一次可可娜和帕比卡進入了一個神奇的異世界,裏面全部是數據結構題。
她們終於做出了所有題,拿到了碎片,正準備離開,突然發現離開的出口上還有最後一道題沒被AC,這個題是這樣的:
技術分享

一個序列a,一個操作:
每次詢問一個區間,是否存在兩個不同數x,y,使得x = y * z,這裏指的是整除!

INPUT第一行兩個數n,m第二行n個數表示a序列後面有m行,每行為l r z表示一個操作OUTPUT對於每個操作,輸出”flip”表示可以,輸出“flap”表示不可以SAMPLE INPUT5 51 2 4 8 161 2 22 4 44 5 21 2 82 4 5SAMPLE OUTPUTflipflipflipflapflapHINTn,m,a[i] <= 1000002 <= z <= 100000SOLUTION“玲瓏杯”ACM比賽 Round #14

標程:

#include<bits/stdc++.h> #define MAXN 100010   using namespace std;   int n , m , block , a[ MAXN ], belong[ MAXN ] , ans[ MAXN ] , cnt[ MAXN ] , last[ MAXN ];   struct ask {         int v , l , r , pos; } q[ MAXN ];   vector < ask > linker[MAXN ];   inline bool cmp( const ask& a , const ask & b ) {         return belong[ a.l ] ^ belong[ b.l ] ? belong[ a.l ] <belong[ b.l ] : belong[ a.l ] & 1 ? a.r < b.r : a.r > b.r; }   inline int read() {         register int x = 0 , ch = getchar();         while( !isdigit( ch ) ) ch = getchar();         while( isdigit( ch ) ) x = x * 10 + ch - ‘0‘ , ch =getchar();         return x; }   int main() {         n = read() , m = read();         block = n / sqrt( m / 3 );         for( register int i = 1 ; i <= n ; i++ ) belong[i] = ( i -1 ) / block , a[i] = read();         for( register int i = 1 ; i <= m ; i++ )                q[i].l = read() , q[i].r = read() , q[i].v = read() ,q[i].pos = i;         sort( q + 1 , q + m + 1 , cmp );         for( int i = 1 , l = 1 , r = 0 ; i <= m ; i++ )         {                while( l > q[i].l ) cnt[ a[ --l ] ]++;                while( r < q[i].r ) cnt[ a[ ++r ] ]++;                while( l < q[i].l ) cnt[ a[ l++ ] ]--;                while( r > q[i].r ) cnt[ a[ r-- ] ]--;                if( q[i].v > 300 )                        for( register int j = 1 ; j * q[i].v <=100000 && !ans[ q[i].pos ] ; j++ )                                if( cnt[j] && cnt[ j * q[i].v] )                                       ans[ q[i].pos ] = 1;         }         for( int x = 1 ; x <= 300 ; x++ )         {                 for( registerint i = 1 ; i <= n ; i++ ) linker[i].clear();                for( register int i = 1 ; i <= m ; i++ )                        if( q[i].v == x )                                linker[ q[i].l ].push_back( q[i] );                memset( last , 0x3f , sizeof( last ) );                for( register int i = n , j = n + 1 ; i ; i-- )                {                        if( a[i] * 1ll * x <= 100000 ) j = min( j ,last[ a[i] * 1ll * x ] );                        if( a[i] % x == 0 ) j = min( j , last[ a[i] /x ] );                        for( register int k = 0 ; k <linker[i].size() ; k++ )                                if( linker[i][k].r >= j )                                       ans[ linker[i][k].pos ] = 1;                        last[ a[i] ] = i;                }         }         for( register int i = 1 ; i <= m ; i++ )                puts( ans[i] ? "flip" : "flap" );         return 0; }       

E -- 大頭日

Time Limit:2s Memory Limit:256MByte

Submissions:69Solved:3

DESCRIPTION

技術分享
懟大佬是會掉人品的,如果懟成功了,那麽rp--,否則rp不變。
有n個大佬,任意兩個大佬之間都互相懟了一次,他們之間必有一個懟對方成功,而另一個失敗。
具體來說,這形成了一個競賽圖,即任意兩點之間有且僅有一條有向邊。
每個大佬的初始rp都是0,他們互相懟之後把所有人的rp排序,問有多少種本質不同的rp序列?

INPUT一行一個整數表示n。OUTPUT一行一個整數表示答案模998244353的值。SAMPLE INPUT1SAMPLE OUTPUT1HINTn <= 100000SOLUTION“玲瓏杯”ACM比賽 Round #14

標程:

#include <bits/stdc++.h> #define xx first #define yy second #define mp make_pair #define pb push_back #define fill( x, y ) memset( x, y, sizeof x ) #define copy( x, y ) memcpy( x, y, sizeof x )  using namespace std;  typedef long long LL; typedef pair < int, int > pa;  inline int read() { 	int sc = 0, f = 1; char ch = getchar(); 	while( ch < ‘0‘ || ch > ‘9‘ ) { if( ch == ‘-‘ ) f = -1; ch = getchar(); } 	while( ch >= ‘0‘ && ch <= ‘9‘ ) sc = sc * 10 + ch - ‘0‘, ch = getchar(); 	return sc * f; }  const int mod = 998244353; const int MAXN = 262145;  inline int qpow(int x, int y, int mod) { int ret = 1; for( ; y ; y >>= 1, x = 1LL * x * x % mod ) if( y & 1 ) ret = 1LL * ret * x % mod; return ret; }  namespace NTT { 	int R[MAXN], n, L, inv;  	inline void getR() { for( int i = 0 ; i < n ; i++ ) R[ i ] = ( R[ i >> 1 ] >> 1 ) | ( ( i & 1 ) << L - 1 ); inv = qpow( n, mod - 2, mod ); }  	inline void NTT(int *a, int f) 	{ 		for( int i = 0 ; i < n ; i++ ) if( i < R[ i ] ) swap( a[ i ], a[ R[ i ] ] ); 		for( int i = 1, wn = qpow( 3, mod - 1 + f * ( mod - 1 ) / ( i << 1 ), mod ) ; i < n ; i <<= 1, wn = qpow( 3, mod - 1 + f * ( mod - 1 ) / ( i << 1 ), mod ) ) 			for( int j = 0, w = 1; j < n ; j += i << 1, w = 1 ) 				for( int k = 0 ; k < i ; k++, w = 1LL * w * wn % mod ) 				{ 					int x = a[ j + k ], y = 1LL * w * a[ j + k + i ] % mod; 					a[ j + k ] = ( x + y ) % mod; a[ j + k + i ] = ( x - y + mod ) % mod; 				} 		if( f < 0 ) for( int i = 0 ; i < n ; i++ ) a[ i ] = 1LL * a[ i ] * inv % mod; 	}  	inline void mul(int *ret, int *a, int *b) 	{ 		NTT( a, 1 ); NTT( b, 1 ); 		for( int i = 0 ; i < n ; i++ ) ret[ i ] = 1LL * a[ i ] * b[ i ] % mod; 		NTT( ret, -1 ); 	} }  inline void inc(int &x, int y) { x += y; if( x >= mod ) x -= mod; } inline void dec(int &x, int y) { x -= y; if( x < 0 ) x += mod; }  int n, f[MAXN], g[MAXN], fac[MAXN], inv[MAXN], fnv[MAXN], p[MAXN], p_cnt, phi[MAXN], a[MAXN], b[MAXN], c[MAXN];  inline int C(int x, int y) { return 1LL * fac[ x ] * fnv[ y ] % mod * fnv[ x - y ] % mod; }  inline void init() { 	fac[ 0 ] = inv[ 0 ] = inv[ 1 ] = fnv[ 0 ] = phi[ 1 ] = f[ 0 ] = 1; 	for( int i = 1 ; i <= ( n << 1 ) ; i++ ) fac[ i ] = 1LL * fac[ i - 1 ] * i % mod;    	for( int i = 2 ; i <= ( n << 1 ) ; i++ ) inv[ i ] = 1LL * ( mod - mod / i ) * inv[ mod % i ] % mod;    	for( int i = 1 ; i <= ( n << 1 ) ; i++ ) fnv[ i ] = 1LL * fnv[ i - 1 ] * inv[ i ] % mod; 	for( int i = 2 ; i <= n ; i++ ) 	{ 		if( !phi[ i ] ) phi[ p[ ++p_cnt ] = i ] = i - 1; 		for( int j = 1 ; i * p[ j ] <= n ; j++ ) 		{ 			if( i % p[ j ] == 0 ) 			{ 				phi[ i * p[ j ] ] = phi[ i ] * p[ j ]; 				break; 			} 			phi[ i * p[ j ] ] = phi[ i ] * ( p[ j ] - 1 ); 		} 	} 	for( int i = 1 ; i <= n ; i++ ) 	{ 		int t = C( i << 1, i ); 		for( int j = i, k = 1 ; j <= n ; j += i, k++ ) 			if( i & 1 ) dec( g[ j ], 1LL * phi[ k ] * t % mod ); 			else inc( g[ j ], 1LL * phi[ k ] * t % mod ); 		if( i & 1 ) g[ i ] = ( mod - g[ i ] ) % mod; 		g[ i ] = 1LL * g[ i ] * inv[ i << 1 ] % mod; 	} }  inline void solve(int l, int r) { 	if( l == r ) { f[ l ] = 1LL * f[ l ] * inv[ l ] % mod; return ; } 	int mid = l + r >> 1; 	solve( l, mid ); 	for( NTT::n = 1, NTT::L = 0 ; NTT::n <= r - l + 1 ; NTT::n <<= 1 ) NTT::L++; 	NTT::getR(); 	for( int i = 0 ; i < NTT::n ; i++ ) 		a[ i ] = i + l <= mid ? f[ i + l ] : 0, b[ i ] = ( i + l + 1 ) <= r ? g[ i + 1 ] : 0; 	NTT::mul( c, a, b ); 	for( int i = mid + 1 ; i <= r ; i++ ) 		inc( f[ i ], c[ i - l - 1 ] ); 	solve( mid + 1, r ); }  int main() { 	n = read(); 	init(); 	solve( 0, n ); 	return printf( "%d\n", f[ n ] ), 0; }


“玲瓏杯”算法比賽 Round #14題目與標程