Codeforces Round #407 (Div. 2)解題報告

A:Anastasia and pebbles

水題。。直接按題意搞一下就行了

B:Masha and geometric depression

同樣是一個模擬題,map記錄bad數,特判q=-1和q=1的情況即可

C:Functions again

……好像說是最大子段和?

看別人題解代碼很長的樣子  我是記錄前綴和的最大最小值,貪心一下就行了,因爲正負對最大最小值的影響其實是沒有的,所以不需要考慮太多

然後……要注意最小值如果大於0可以認爲不取更優

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <cstring>
#include <ctime>
#include <vector>
#define inf 1e9
#define ll long long
#define For(i,j,k) for(int i=j;i<=k;i++)
#define Dow(i,j,k) for(int i=k;i>=j;i--)
using namespace std;
ll n,ma,mi,s[500001],a[500001];
int main()
{
	scanf("%I64d",&n);
	For(i,1,n)	scanf("%I64d",&a[i]);
	For(i,2,n)
	{
		s[i]=s[i-1]+abs(a[i]-a[i-1])*(i&1?-1:1);
		ma=max(ma,s[i]);mi=min(mi,s[i]);
	}
	printf("%I64d",ma-min(0LL,mi));
}
D:Weird journey

拿到題一點思路都沒有,開始在草稿紙上亂畫……

但是發現,不論怎麼畫,兩條只走一次的邊一定有一個公共點

然後考慮自環這個特殊情況,唯一有可能沒有公共點的情況

嗯……這個結論是瞎猜的,但是過了  不會證啊OTZ

然後記錄自環數量爲cnt2,顯然,選兩個自環可行。對答案貢獻爲cnt2*(cnt2-1)/2

一個自環,一條正常的邊,也可行,記錄正常邊條數爲cnt1,對答案貢獻cnt2*cnt1

接下來是考慮公共點,我們輸入邊的時候記錄num[i]表示與i相連的邊的數量,那麼i這個點對於答案的貢獻爲num[i]*(num[i]-1)/2

累加即可


但是上面所有的想法,都要在圖聯通的情況下才可以,因此先bfs判斷一下圖的連通性

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <cstring>
#include <ctime>
#include <vector>
#define inf 1e9
#define maxn 2000050
#define ll long long
#define For(i,j,k) for(ll i=j;i<=k;i++)
#define Dow(i,j,k) for(ll i=k;i>=j;i--)
using namespace std;
ll cnt,ans,cnt1,cnt2,poi[maxn],vis[maxn],q[maxn],nxt[maxn],f[maxn],n,m,x,y,num[maxn];
bool bj[maxn];
inline void add(ll x,ll y)
{
	poi[++cnt]=y;nxt[cnt]=f[x];f[x]=cnt;
}
inline void BFS(int x)
{
	ll l=1,r=1;q[1]=x;
	vis[x]=1;
	while(l<=r)
	{
		ll x=q[l];
		for(ll i=f[x];i;i=nxt[i])
			if(!vis[poi[i]])
				vis[poi[i]]=1,q[++r]=poi[i];
		l++;
	}
	For(i,1,n)	if(!vis[i]&&bj[i])	{puts("0");exit(0);}
}
int main()
{
	scanf("%lld%lld",&n,&m);
	ll s;
	For(i,1,m)
	{
		scanf("%lld%lld",&x,&y);
		bj[x]=bj[y]=1;
		s=x;
		if(x==y)	cnt1++;
		else
		{
			cnt2++;add(x,y);add(y,x);num[x]++;num[y]++;
		}
	}
	BFS(s);
	For(i,1,n)	if(!vis[i]&&bj[i])	{puts("0");return 0;}
	ans=cnt1*cnt2+(cnt1*cnt1-cnt1)/2;
	For(i,1,n)	ans+=num[i]*(num[i]-1)/2;
	printf("%I64d",ans);
}
E:The Great Mixing

個人認爲……比D題簡單一些

題意可知,我們每多取一個濃度爲x/1000的藥水,則分母+1000,分子+x

所以顯然可以得到,如果我們選了t瓶藥水,則其sigma(x)需要達到t*k,k爲目標濃度的分子

因此我們可以認爲,一瓶藥水的分母爲答案貢獻了-k,分子爲答案貢獻了x

則這瓶藥水總貢獻爲x-k

我們只需要選出一些藥水讓sigma(x-k)等於0就行了

題目中n<=1e6,但是……a[i]<=1000,所以很顯然的是最多隻有1001種不同的藥,可以無限取,所以多出來的完全沒有貢獻

即本題中,對答案有貢獻的物品至多1001個

然後因爲藥品濃度不小於0,不大於1,所以很顯然的又得到了我們可行的狀態範圍……-1000~1000

這種範圍。。。

BFS直接上啊

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <cstring>
#include <ctime>
#include <vector>
#define inf 1e9
#define ll long long
#define For(i,j,k) for(int i=j;i<=k;i++)
#define Dow(i,j,k) for(int i=k;i>=j;i--)
using namespace std;
int n,k,a[10001],f[10001],l=1,r=0,q[100001],vis[10001],N;
map<int,int>bj;
inline void bfs()
{
	while(l<=r)
	{
		int t=q[l];
		if(t==4001){printf("%d",f[4001]);exit(0);}
		For(i,1,n)
		{
			int tmp=t+a[i];
			if(f[tmp])	continue;
			if(tmp<2000||tmp>6002)	continue;
			f[tmp]=f[t]+1;q[++r]=tmp;
		}
		l++;
	}
	puts("-1");
}
int main()
{
	scanf("%d%d",&k,&n);
	For(i,0,10000)	f[i]=0;
	For(i,1,n)	
	{
		int x;
		scanf("%d",&x);x-=k;
		if(bj[x+4001])	continue;
		bj[x+4001]=1;a[++N]=x;q[++r]=x+4001;f[x+4001]=1;
	}
	n=N;
	bfs();
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章