小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

[貪心專題]CF549G,CF351E,CF226D,CF1276C,CF1148E,CF798D

 印度阿三17 2020-07-26

目錄

T1:CF1276C Beautiful Rectangle

title

solution

在這里插入圖片描述保證不重復(fù),我們就按對(duì)角線這樣填下去就可以了,這個(gè)很好想到
但注意行,列的變換不要這么寫(xiě),因?yàn)榭赡苁翘厥獾恼叫?/p>

r = ( r   1 ) % row;
c = ( c   1 ) % col;

接下來(lái)返回考慮怎樣確定這個(gè)矩陣的大小\(row,col\),要求\(row<=col\)
我們可以暴力枚舉\(row\)
也就是說(shuō)每一個(gè)數(shù)的最多出現(xiàn)次數(shù)要求一定小于等于\(row\),不然肯定有一行會(huì)有重復(fù)數(shù)字
然后我們把這些數(shù)字出現(xiàn)次數(shù)加起來(lái),就能計(jì)算出列
注意在判斷矩陣大小的時(shí)候必須\(row*col\)來(lái)判斷,不能單純按統(tǒng)計(jì)的數(shù)字最多出現(xiàn)次數(shù)
因?yàn)椴灰欢苷齖(row\),所以有些數(shù)不一定達(dá)到了上限的

code

#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define MAXN 400005
vector < pair < int, int > > g;
vector < vector < int > > ans;
vector < int > num;
int n, row, col;
int a[MAXN], b[MAXN], cnt[MAXN];

int main() {
	scanf( "%d", &n );
	for( int i = 1;i <= n;i    )
		scanf( "%d", &a[i] ), b[i] = a[i];
	sort( a   1, a   n   1 );
	int m = unique( a   1, a   n   1 ) - a - 1;
	for( int i = 1;i <= n;i    ) b[i] = lower_bound( a   1, a   m   1, b[i] ) - a;
	for( int i = 1;i <= n;i    ) cnt[b[i]]   ;
	for( int i = 1;i <= m;i    ) g.push_back( make_pair( cnt[i], i ) );
	sort( g.begin(), g.end() );
	int now = 0;
	for( int i = 1;i <= sqrt( n );i    ) {
		int temp = 0;
		for( int j = 0;j < g.size();j    )
			temp  = min( g[j].first, i );
		if( temp / i < i ) continue;
		else if( temp / i * i > now ) now = temp / i * i, row = i, col = temp / i;
	}
	printf( "%d\n%d %d\n", row * col, row, col );
	reverse( g.begin(), g.end() );
	for( int i = 0;i < g.size();i    ) {
		for( int j = 1;j <= min( g[i].first, row );j    )
			num.push_back( g[i].second );
	}
	ans.resize( row );
	for( int i = 0;i < row;i    ) ans[i].resize( col );
	int r = 0, c = 0;
	for( int i = 0;i < num.size();i    ) {
		ans[r][c] = num[i];
		r   , c   ;
		if( r == row ) r = 0, c -= row - 1;
		if( c < 0 ) c  = col;
		if ( c >= col ) c -= col;
	}
	for( int i = 0;i < row;i    ) {
		for( int j = 0;j < col;j    )
			printf( "%d ", a[ans[i][j]] );
		printf( "\n" );
	}
	return 0;
}

T2:CF226D The table

title

solution

本質(zhì)就是個(gè)暴力
對(duì)于總和小于零的每一行,每一列都進(jìn)行取反操作即可
當(dāng)某一行或某一列操作次數(shù)為偶數(shù)的時(shí)候,其實(shí)相當(dāng)于是無(wú)效操作,最后輸出答案的時(shí)候判掉即可
為什么這么暴力就可以?——因?yàn)槲覀兿拗屏瞬僮鞯目偞螖?shù)極限就是\(1e6\)
把每一行和每一列的和加起來(lái)等于整個(gè)矩陣的總和的兩倍,值域\([-4e6,4e6]\)
每次取反至少是\(-1=>1\),整個(gè)矩陣總和的兩倍至少增加\(4\),當(dāng)和無(wú)法再增加的時(shí)候就是每一行每一列都大于零

code

#include <cstdio>
#include <vector>
using namespace std;
#define MAXN 105
vector < int > r, c;
int n, m;
int row[MAXN], col[MAXN], visr[MAXN], visc[MAXN];
int a[MAXN][MAXN];

int main() {
	scanf( "%d %d", &n, &m );
	for( int i = 1;i <= n;i    )
		for( int j = 1;j <= m;j    ) {
			scanf( "%d", &a[i][j] );
			row[i]  = a[i][j];
			col[j]  = a[i][j];
		}
	while( 1 ) {
		bool flag = 1;
		for( int i = 1;i <= n;i    )
			if( row[i] < 0 ) {
				visr[i]   ;
				row[i] = - row[i];
				for( int j = 1;j <= m;j    )
					col[j] -= ( a[i][j] << 1 ), a[i][j] = - a[i][j];
				flag = 0;
				break;
			}
		for( int i = 1;i <= m;i    ) 
			if( col[i] < 0 ) {
				visc[i]   ;
				col[i] = - col[i];
				for( int j = 1;j <= n;j    )	
					row[j] -= ( a[j][i] << 1 ), a[j][i] = - a[j][i];
				flag = 0;
				break;
			}
		if( flag ) break;
	}
	for( int i = 1;i <= n;i    )
		if( visr[i] & 1 ) r.push_back( i );
	for( int i = 1;i <= m;i    )
		if( visc[i] & 1 ) c.push_back( i );
	printf( "%d", r.size() );
	for( int i = 0;i < r.size();i    )
		printf( " %d", r[i] );
	printf( "\n%d", c.size() );
	for( int i = 0;i < c.size();i    )
		printf( " %d", c[i] );
	return 0;
}

T3:CF549G Happy Line

title

solution

非常巧的一個(gè)點(diǎn)——對(duì)于第\(i\)個(gè)數(shù),不管它以后的位置在哪,它原來(lái)的下標(biāo)\(i\)值與\(val\)的和是個(gè)定值
所以貪心就想到總和越大的越應(yīng)該往后放
這樣才有可能不減
如果有一個(gè)數(shù)\(i\)的總和大于最后一個(gè)數(shù)的總和且在前面某個(gè)位置,那么數(shù)\(i\)的值就等于總和減去現(xiàn)在的下標(biāo),本來(lái)值就比最后一個(gè)大,減去的又比最后一個(gè)小,自然就不可能成為不減序列

code

#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 200005
struct node {
	int val, id;
}v[MAXN];
int n;

bool cmp( node x, node y ) {
	return x.val   x.id < y.val   y.id;
}

int main() {
	scanf( "%d", &n );
	for( int i = 1;i <= n;i    )
		scanf( "%d", &v[i].val ), v[i].id = i;
	sort( v   1, v   n   1, cmp );
	for( int i = 1;i <= n;i    )
		if( v[i].id   v[i].val == v[i - 1].id   v[i - 1].val )
			return ! printf( ":(" );
		else if( i > v[i].id   v[i].val ) return ! printf( ":(");
	for( int i = 1;i <= n;i    )
		printf( "%d ", v[i].id   v[i].val - i );
	return 0;
}

T4:CF798D Mike and distribution

title

solution

\[2*\sum_{i=1}^xa[p[i]]>\sum_{j=1}^na[j],2*\sum_{i=1}^xb[p[i]]>\sum_{j=1}^nb[j] \]

不管是\(a\)還是\(b\)數(shù)組,都減去一倍已選的數(shù)
其實(shí)最后的要求都轉(zhuǎn)化為了,\(a,b\)數(shù)組已選的數(shù)的和要大于沒(méi)選的數(shù)的和
從\(\lfloor \frac{n}{2}\rfloor 1\)這個(gè)特別要求入手
考慮分奇偶討論
當(dāng)\(n=2k\)
按\(a\)的從大到小排序,并兩兩分組
第一組的全選上,之后的每一組選擇\(b\)較大的一個(gè)
接下來(lái)證明這個(gè)算法的正確性
我們每一組都選的\(b\)較大的一個(gè),自然可以壓制另一個(gè)的\(b\),\(b\)的要求已經(jīng)達(dá)到
那么\(a\)怎么辦呢?
如果較大的\(b\)的\(a\)也較大,那自然更好,甭考慮
如果是較小的\(a\),也不用害怕,因?yàn)槲覀兊谝唤M的兩個(gè)\(a\)都選了
它們一定大于這一組里面較大的\(a\),可以壓制
那么后面遇到類似情況怎么辦,最大的兩個(gè)\(a\)已經(jīng)用了,沒(méi)關(guān)系
兩個(gè)\(a\)用了,一定解救出前面較大的某些(個(gè))\(a\),拿來(lái)壓制現(xiàn)在的\(a\)
就這么一個(gè)一個(gè)壓制下去,最后讓\(a\)也達(dá)到要求
奇數(shù)同理可得,不再重復(fù)

code

#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 100005
struct node {
	int a, b, id;
}v[MAXN];
int n;

bool cmp( node x, node y ) {
	return x.a > y.a;
}

int main() {
	scanf( "%d", &n );
	for( int i = 1;i <= n;i    )
		scanf( "%d", &v[i].a ), v[i].id = i;
	for( int i = 1;i <= n;i    )
		scanf( "%d", &v[i].b );
	sort( v   1, v   n   1, cmp );
	printf( "%d\n", ( n >> 1 )   1 );
	if( n % 2 ) {
		printf( "%d ", v[1].id );
		for( int i = 2;i <= n;i  = 2 )
			if( v[i].b > v[i   1].b ) printf( "%d ", v[i].id );
			else printf( "%d ", v[i   1].id );
	}
	else {
		printf( "%d %d ", v[1].id, v[2].id );
		for( int i = 3;i <= n;i  = 2 )
			if( v[i].b > v[i   1].b ) printf( "%d ", v[i].id );
			else printf( "%d ", v[i   1].id );
	}
	return 0;
}

T5:CF351E Jeff and Permutation

title

solution

考慮數(shù)\(a,b\),且\(|a|>|b|\)
①\(a\)取\( \)
如果\(b\)在\(a\)前面,不管\(b\)取\(±\)都不會(huì)有逆序?qū)?br>如果\(b\)在\(a\)后面,不管\(b\)取\(±\)都會(huì)有逆序?qū)?br>②\(a\)取\(-\)
如果\(b\)在\(a\)前面,不管\(b\)取\(±\)都不會(huì)有逆序?qū)?br>如果\(b\)在\(a\)后面,不管\(b\)取\(±\)都會(huì)有逆序?qū)?/p>

我們發(fā)現(xiàn),逆序?qū)Φ漠a(chǎn)生只與兩個(gè)數(shù)的相對(duì)位置以及較大數(shù)的正負(fù)有關(guān)

所以我們只需要考慮對(duì)于下標(biāo)為\(i\)的數(shù),前面絕對(duì)值比他小的有多少個(gè),后面比他小的有多少個(gè),取個(gè)\(min\)即可
至于比他大的數(shù)自然是交個(gè)比他大的數(shù)來(lái)管他們之間是否會(huì)有逆序?qū)?,不管這個(gè)數(shù)取正取負(fù),逆序?qū)Χ荚谳^大數(shù)的決定上
所以彼此是相互獨(dú)立的,不會(huì)造成影響

那么兩個(gè)數(shù)的絕對(duì)值一樣的時(shí)候呢?這個(gè)時(shí)候的正負(fù)不就有影響了嗎?
所以我們?cè)摱x一個(gè)\(dp[i][j]:\)前\(i\)個(gè)數(shù)有\(zhòng)(j\)個(gè)為\(-\),然后進(jìn)行轉(zhuǎn)移
其實(shí)并不需要,可以證明絕對(duì)值一樣的數(shù)一定會(huì)是前面一段全選負(fù)后面一段全是正
假設(shè)下標(biāo)\(i<j\)且\(|a[i]|=|a[j]|\)
如果\(i\)選了正,意味著數(shù)列\(zhòng)([1,i)\)個(gè)絕對(duì)值比\(i\)小的個(gè)數(shù)多于\((i,n]\)的個(gè)數(shù)
那么\(j\)而言,前面的數(shù)已經(jīng)包含了\([1,i)\),還多加了一段\((i,j)\),那么前面絕對(duì)值小于它的數(shù)個(gè)數(shù)只會(huì)增加(不變)不會(huì)減小,后面\((j,n]\)則只會(huì)減?。ú蛔儯┎粫?huì)增大
所以是不會(huì)彼此之間產(chǎn)生逆序?qū)Φ模凑丈厦婷總€(gè)數(shù)獨(dú)立判斷的做法做即可

code

#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 2005
int n, ans;
int p[MAXN];

int main() {
	scanf( "%d", &n );
	for( int i = 1;i <= n;i    )
		scanf( "%d", &p[i] );
	for( int i = 1;i <= n;i    ) {
		int Left = 0, Right = 0;
		for( int j = 1;j < i;j    )
			if( fabs( p[i] ) <= fabs( p[j] ) ) continue;
			else Left   ;
		for( int j = i   1;j <= n;j    )
			if( fabs( p[i] ) <= fabs( p[j] ) ) continue;
			else Right   ;
		ans  = min( Left, Right );
	}
	printf( "%d", ans );
	return 0;
}

T6:CF1148E Earth Wind and Fire

title

solution

很常規(guī)的貪心思想,按值排序后,然后下標(biāo)一一對(duì)應(yīng),即\(s[i]\)負(fù)責(zé)成為\(t[i]\)
然后我們從最大的開(kāi)始往下判斷,要知道\(s\)一定先把多余的可以傳遞的傳遞給臨近的
因?yàn)槿绻鸤(i\)把多余的分給離他很遠(yuǎn)的\(s[j]\),則\(s[j]<=s[i 1]\)
就算加上了\(s[i]\)給的\(x\),\(s[j],s[i 1]\)之間的差距也不如將\(x\)分給\(s[i 1]\)優(yōu)
差距越大能傳遞的\(d\)越大
同時(shí)傳遞后要保證\(s[i]>=t[i]\),當(dāng)循環(huán)到某一個(gè)數(shù)后,發(fā)現(xiàn)他的\(s<t\),則無(wú)解
因?yàn)槲覀儚拇蟮叫∫灰粠头鲞^(guò)來(lái)
此時(shí)的數(shù)一定接受了比他大的所有的數(shù)多出來(lái)的\(t[]-s[]\)
全加上也沒(méi)到要求
后面的數(shù)也幫不了它,因?yàn)閈(s[該數(shù)]>=s[后面的數(shù)]\),無(wú)法進(jìn)行轉(zhuǎn)移

code

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define MAXN 300005
#define int long long
struct node {
	int val, id;
}s[MAXN], t[MAXN];
struct noded {
	int l, r, val;
	noded( int L, int R, int V ) {
		l = L, r = R, val = V;
	}
};
vector < noded > ans;
int n, sums, sumt;

bool cmp( node x, node y ) {
	return x.val > y.val;
}

signed main() {
	scanf( "%d", &n );
	for( int i = 1;i <= n;i    ) {
		scanf( "%d", &s[i].val );
		s[i].id = i, sums  = s[i].val;
	}
	for( int i = 1;i <= n;i    ) {
		scanf( "%d", &t[i].val );
		t[i].id = i, sumt  = t[i].val;
	}
	if( sums != sumt ) return ! printf( "NO" );
	sort( s   1, s   n   1, cmp );
	sort( t   1, t   n   1, cmp );
	int last = 1;
	for( int i = 1;i <= n;i    ) {
		if( s[i].val < t[i].val ) return ! printf( "NO" );
		while( s[i].val > t[i].val ) {
			while( t[last].val <= s[last].val ) last   ;
			int temp;
			temp = min( t[last].val - s[last].val, s[i].val - t[i].val );
			temp = min( temp, ( s[i].val - s[last].val ) >> 1 );
			s[i].val -= temp, s[last].val  = temp;
			ans.push_back( noded( s[last].id, s[i].id, temp ) );
		}
	}
	printf( "YES\n%d\n", ans.size() );
	for( int i = 0;i < ans.size();i    )
		printf( "%lld %lld %lld\n", ans[i].l, ans[i].r, ans[i].val );
	return 0;
}
來(lái)源:https://www./content-4-723401.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多