1. 程式人生 > >【Codeforces】Round #523 (Div. 2) A-F

【Codeforces】Round #523 (Div. 2) A-F

A. Coins

貪心選儘量大的填

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int n,s,ans;

int main(){
	int i,j,mx;
    scanf("%d%d",&n,&s);
    for(i=min(n,s);i && s;--i) if(s>=i){
         ans+=s/i;s%=i;
	}
	printf("%d",ans);
}

B. Views Matter

離散化高度後,判斷每兩個高度間隔之間的列數,貪心先沿著對角線往後填,不夠的強制填到這個高度的最後一列。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,m,a[N],vs[N],op,mx;
ll ans,ss;

int main(){
	int i,j,k,mx=0,dc=0,dir=1;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i){
    	scanf("%d",&a[i]);ss+=a[i];
	}
	sort(a+1,a+n+1);
	mx=a[n];k=0;
    for(i=j=1;i<=n;i=j){
    	for(;j<=n && a[j]==a[i];++j);
    	dir+=min(n-dir+1,a[i]-dc);
    	ans+=a[i]-dc+max(0,j-dir);
		dc=a[i];dir=max(dir,j);
	}
	printf("%I64d",ss-ans);
    return 0;
}

C. Multiplicity

ai\sqrt a_i列舉之後dpdpf[i]f[i]為長度為iibb陣列方案即可。

#include<bits/stdc++.h>
const int inf=1886417009;
using namespace std;
typedef long long ll;
const int N=510,M=1e6+10;

int n,m,inn,ott,val[N],S,T,vs[N],tim,sum;
int head[N<<1],to[M],nxt[M],w[M],cc[M],tot=1;
int cur[N<<1],dis[N<<1],stk[N],top;

inline void fl(){printf("-1");exit(0);}

inline void lk(int u,int v,int flw,int cst)
{
	to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=flw;cc[tot]=cst;
	to[++tot]=u;nxt[tot]=head[v];head[v]=tot;w[tot]=0;cc[tot]=-cst;
}

struct Gra{
	int head[N],to[N],nxt[N],tot,rt;
	int dmd[N],col[N],dl[N];
	
	inline void lk(int u,int v)
	{
	   to[++tot]=v;nxt[tot]=head[u];head[u]=tot;
	   to[++tot]=u;nxt[tot]=head[v];head[v]=tot;
	}
	
	void dfs(int x,int fa)
	{
		int i,j;
		for(i=head[x];i;i=nxt[i]){
			j=to[i];if(j==fa) continue;
			dfs(j,x);
		}
		stk[++top]=x;if(!dmd[x]) return;
		for(i=1;i<=top;++i) col[stk[i]]=x;
		for(i=1;i<top;++i) dl[x]-=dmd[stk[i]];
		if(dl[x]<0) fl();top=0;
	}
}A,B;

priority_queue<Pr>que;
inline bool spfa()
{
	memset(dis,0x8f,sizeof(dis));
	f
}

int main(){
	 int i,j,x,y,z;
	 scanf("%d%d%d",&n,&A.rt,&B.rt);S=(n<<1)+1;T=S+1;
	 for(i=1;i<=n;++i) scanf("%d",&val[i]);
	 for(i=1;i<n;++i){scanf("%d%d",&x,&y);A.lk(x,y);}
	 for(i=1;i<n;++i){scanf("%d%d",&x,&y);B.lk(x,y);}
	 for(scanf("%d",&z);z;--z) {scanf("%d%d",&x,&y);A.dmd[x]=A.dl[x]=y;}
	 for(scanf("%d",&z);z;--z) {scanf("%d%d",&x,&y);B.dmd[x]=B.dl[x]=y;}
	 A.dfs(A.rt,0);B.dfs(B.rt,0);
	 for(i=1;i<=n;++i) if(A.dl[i]) lk(S,i,A.dl[i],0),inn+=A.dl[i];
	 for(i=1;i<=n;++i) if(B.dl[i]) lk(i+n,T,B.dl[i],0),ott+=B.dl[i];
	 if(inn!=ott) fl();
	 for(i=1;i<=n;++i) lk(A.col[i],n+B.col[i],1,val[i]);
	 for(;spfa();)
	 	for(vs[T]=tim;vs[T]==tim;){
	 		++tim;memcpy(cur,head,sizeof(cur));inn-=dfs(S,inf);
	 	}
	 if(inn!=0) fl();
	 printf("%d",sum);
	 return 0;
}

D. TV Shows

先按ll排序,用線段樹記錄所有沒有後繼的區間的rr值。

每加入一段區間首先線上段樹上二分查詢最大的li\leq l_irr,判斷接或不接的最小花費。

By ccosi, contest: Codeforces Round #523 (Div. 2), problem: (D) TV Shows, Accepted, #
 #include<bits/stdc++.h>
#define mid ((l+r)>>1)
#define lc k<<1
#define rc k<<1|1
using namespace std;
typedef long long ll;
const int N=1e5+10,mod=1e9+7;

int n,a,b,m,rv[N<<1],cnt,tot;
int ans,ss[N<<3];

struct P{
	int l,r;
	bool operator<(const P&ky)const{
	    return l<ky.l;
	}
}le[N];

struct Q{
	int v,id,sd;
	bool operator<(const Q&ky)const{
	   return v<ky.v;
	}
}q[N<<1];

int ask(int k,int l,int r,int R)
{
	if(!ss[k]) return 0;
	if(l==r) return l;int re=0;
	if(R>mid) re=ask(rc,mid+1,r,R);
	if(!re) re=ask(lc,l,mid,R);
	return re; 
}

void ad(int k,int l,int r,int pos,int vv)
{
	ss[k]+=vv;
	if(l==r) return;
	if(pos<=mid) ad(lc,l,mid,pos,vv);
	else ad(rc,mid+1,r,pos,vv);
}

int main(){
	int i,j,x,y;
	scanf("%d%d%d",&n,&a,&b);
	for(i=1;i<=n;++i){
		scanf("%d%d",&x,&y);
	    q[++cnt]=(Q){x,i,0};
	    q[++cnt]=(Q){y,i,1};
	}
	sort(q+1,q+cnt+1);
	for(i=1;i<=cnt;++i){
		if(q[i].v!=rv[tot]) rv[++tot]=q[i].v;
		if(q[i].sd) le[q[i].id].r=tot;
		else le[q[i].id].l=tot;
	}
	sort(le+1,le+n+1);
	for(i=1;i<=n;++i){
		j=0;
		if(le[i].l>1) j=ask(1,1,tot,le[i].l-1);
		if((!j) || a<=(ll)(rv[le[i].l]-rv[j])*b){
			ans+=(a+(ll)b*(rv[le[i].r]-rv[le[i].l])%mod)%mod;
		    ans%=mod;
			ad(1,1,tot,le[i].r,1);
		}else{
			ans+=(ll)b*(rv[le[i].r]-rv[j])%mod;
			ans%=mod;
			ad(1,1,tot,j,-1);ad(1,1,tot,le[i].r,1);
		}
	}
	printf("%d",ans);
	return 0;
}

E. Politics

最大費用最大流,設第一顆樹中的點為1n1-n,第二顆樹中的點為(n+1)(n+n)(n+1)-(n+n)。設xix_i為對ii號節點的總數限制。

從源點向i(1in)i(1\leq i\leq n)連一條流量為xijsubixjx_i-\sum \limits_{j\in sub_i}x_j(jsubij\in sub_i表示jjii子樹內且jjii路徑上沒有其它有限制的點),費用為00的邊。

i(n+1in+n)i(n+1\leq i\leq n+n)向匯點連一條流量為xijsubixjx_i-\sum\limits_{j\in sub_i}x_j,費用為00的邊。

colicol_i表示深度最大的滿足ii在其子樹內的有限制結點(包括ii本身)。
colicol_icoli+ncol_{i+n}連一條流量為1,費用為aia_i的邊。

跑最大費用最大流即可。

#include<bits/stdc++.h>
const int inf=0x3f3f3f3f;
using namespace std;
typedef long long ll;
const int N=510,M=2e6+10;

int n,m,inn,ott,val[N],S,T,sum,rta,rtb,dmd[N<<1],col[N<<1];
int head[N<<1],to[M],nxt[M],w[M],cc[M],tot;
int dis[N<<1],pre[N<<1],bel[N<<1];bool inq[N<<1];

inline void fl(){printf("-1");exit(0);}

inline void lk(int u,int v,int flw,int cst)
{
	to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=flw;cc[tot]=cst;
	to[++tot]=u;nxt[tot]=head[v];head[v]=tot;w[tot]=0;cc[tot]=-cst;
}

int dfs(int x,int fa,int tpo)
{
	int i,j,re=0;if(dmd[x]) tpo=x;
	col[x]=tpo;
	for(i=head[x];i;i=nxt[i]) if(to[i]!=fa) 
	  re+=dfs(to[i],x,tpo);
	if(dmd[x]){i=dmd[x];dmd[x]-=re;if(dmd[x]<0) fl();re=i;}
	return re;
}

struct Pr{
  int id,v;
  bool operator<(const Pr&ky)const{
     return v<ky.v;
  }
}tp;

queue<int>que;
inline bool spfa()
{
	memset(dis,0x3f,sizeof(dis));
	int i,j,x;dis[S]=0;que.push(S);inq[S]=true;
	for(;que.size();){
		x=que.front();que.pop();
		for(i=head[x];i;i=nxt[i]){
			j=to[i];if((!w[i]) || dis[j]<=dis[x]+cc[i]) continue;
			dis[j]=dis[x]+cc[i];pre[j]=x;bel[j]=i;
			if(!inq[j]) que.push(j),inq[j]=true;
		} 
		inq[x]=false;
	}
	return (dis[T]<inf);
}

int main(){
	 int i,j,x,y,z;
	 scanf("%d%d%d",&n,&rta,&rtb);S=(n<<1)+1;T=S+1;rtb+=n;
	 for(i=1;i<=n;++i) scanf("%d",&val[i]);
	 for(i=1;i<n;++i){scanf("%d%d",&x,&y);lk(x,y,0,0);}
	 for(i=1;i<n;++i){scanf("%d%d",&x,&y);lk(x+n,y+n,0,0);}
	 for(scanf("%d",&z);z;--z) {scanf("%d%d",&x,&y);dmd[x]=y;}
	 for(scanf("%d",&z);z;--z) {scanf("%d%d",&x,&y);dmd[x+n]=y;}
	 dfs(rta,0,rta);dfs(rtb,0,rtb);
	 memset(head,0,sizeof(head));tot=1;
	 for(i=1;i<=n;++i) if(dmd[i]) lk(S,i,dmd[i],0),inn+=dmd[i];
	 for(i=n+1;i<=n+n;++i) if(dmd[i]) lk(i,T,dmd[i],0),ott+=dmd[i];
	 if(inn!=ott) fl();
	 for(i=1;i<=n;++i) 
	   lk(col[i],col[i+n],1,-val[i]);
	 z=inf;
	 for(;spfa();){
 	     for(x=T;x!=S;x=pre[x]) z=min(z,w[bel[x]]);
	     for(x=T;x!=S;x=pre[x])
		   w[bel[x]]-=z,w[bel[x]^1]+=z;
	     sum-=z*dis[T];inn-=z;
	 }
	 if(inn!=0) fl();
	 printf("%d",sum);
	 return 0;
}

F. Lost Root

具體方法是先找到兩個在不同根節點兒子子樹中的葉節點,然後在它們之間的路徑上h2h^2找根。

判斷一個點ii是否為葉結點:
隨機選另一個點jj,然後若所有其它點到jj的路徑都不經過ii,則ii為葉節點。複雜度為O(n)O(n)

找到一個葉結點:
隨機選到葉結點的概率0.5\geq 0.5kk越大,概率越高。20次找不到的概率低到了1220\dfrac{1}{2^{20}}

找到另一個葉結點:隨機選一個點判斷在它與已知葉節點路徑上點數是否為2h12h-1

找到根節點:直接h2h^2排入相對位置即可。

懶得寫了,貼個標程

#include <bits/stdc++.h>
using namespace std;
 
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// #define endl "\n"
#define int long long

const int N=1e5+5;

int n, k, h, leaf1, leaf2;
int a[N];
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
vector<int> v, path;
map<tuple<int, int, int>, int> store;

int query(int a, int b, int c)
{
	tuple<int, int, int> cur=make_tuple(a, b, c);
	if(store.find(cur)!=store.end())
		return (store[cur]);
	cout<<"? "<<a<<" "<<b<<" "<<c<<endl;
	string s;
	cin>>s;
	return (store[cur] = ((s=="Yes")));
}

int print(int x)
{
    cerr<<x;
	cout<<"! "<<x;
	exit(0);
}

int findleaf()
{
	while(true)
	{
		shuffle(a+1, a+n+1, rng);
		int leaf=a[1];
		int random=a[2];
		bool check=1;
		for(int i=3;i<=n;i++)
		{
			check&=(query(random, leaf, a[i])==0);
			if(!check)
				break;
		}
		if(check)
			return leaf;
	}
}

int findleaf2()
{
	while(true)
	{
		int count=0;
		shuffle(a+1, a+n+1, rng);
		if(a[1]==leaf1)
			continue;
		int leaf=a[1];
		bool check=1;
		int cnt=0, reqd=2*(h-1) + 1;
		v.clear();
		for(int i=2;i<=n;i++)
		{
			if(a[i]==leaf1)
				continue;
			int current=query(leaf1, a[i], leaf);
			cnt+=current;
			if(current)
				v.push_back(a[i]);
		}
		if(cnt==reqd)
			return leaf;
	}
}

void findroot()
{
	path.push_back(leaf1);
	path.push_back(v[0]);
	path.push_back(leaf2);
	for(int i=1;i<v.size();i++)
	{
		vector<int> newpath;
		newpath.push_back(path[0]);
		for(int j=1;j<path.size();j++)
		{
			if(query(path[j-1], v[i], path[j]))
			{
				newpath.push_back(v[i]);
				for(int k=j;k<path.size();k++)
					newpath.push_back(path[k]);
				break;
			}
			else
				newpath.push_back(path[j]);
		}
		path=newpath;
	}
	print(path[h]);
}

int32_t main()
{
	cin>>n>>k;
	if(n==1)
	{
	    print(1);
	    return 0;
	}
	int cur=k;
	int nodes=1;
	h=0;
	while(nodes+cur<=n)
	{
		nodes+=cur;
		cur*=k;
		h++;
	}
	for(int i=1;i<=n;i++)
		a[i]=i;
	leaf1=findleaf();
	leaf2=findleaf2();
	findroot();
	return 0;
}

相關推薦

CodeforcesRound #523 (Div. 2) A-F

A. Coins 貪心選儘量大的填 #include<bits/stdc++.h> using namespace std; typedef long long ll; int n,s,ans; int main(){ int i,j,mx

Codeforces Round #524 (Div. 2) A-F

傳送門:CF524Div2 A. Petya and Origami 上取整 #include<bits/stdc++.h> using namespace std; typedef long long ll; int n,m,k;ll a,b,c; i

codeforcesRound #522 (Div. 2) A+B+C+D

目錄 【A. Kitchen Utensils】 【B. Personalized Cup】 【C. Playing Piano】 【D. Barcelonian Distance】  【A. Kitchen Utensils】 題目連結:htt

codeforcesRound #520 (Div. 2) A+B+C+D

目錄 A - A Prank B - Math C - Banh-mi D - Fun with Integers 【A - A Prank】 題目連結:http://codeforces.com/contest/1062/problem/A 【題意】 給你一串序

Codeforces Round #523 (Div. 2) A. Coins

A. Coins 題目連結:https://codeforc.es/contest/1061/problem/A 題意: 給出n和s,要在1-n中選數(可重複),問最少選多少數可以使其和為s。   題解: 貪心就行了。   程式碼如下: #include <c

Codeforces Round #516 (Div. 2) (A~F)

ring 2個 ica extra sdi ref code stdout extras 目錄 A.Make a triangle! B.Equations of Mathematical Magic C.Oh Those Palindromes D.Labyrinth(

Codeforces Round #447 (Div. 2) AQAQ

pro ont 題解 problem fde c語言 span bits endif 【鏈接】 我是鏈接,點我呀:) 【題意】 在這裏輸入題意 【題解】 C語言程序練習題 【代碼】 #include <bits/stdc++.h> using

Codeforces Round #197 (Div. 2) A. Helpful Maths字符串/給一個連加計算式,只包含數字 1、2、3,要求重新排序,使得連加的數字從小到大

asi man title problem beginning 排序 stand should cati A. Helpful Maths time limit per test 2 seconds memory limit per t

Codeforces Round #457 (Div. 2) A Jamie and Alarm Snooze

als lar clu efi out .com bit source fin 【鏈接】 我是鏈接,點我呀:) 【題意】 在這裏輸入題意 【題解】 暴力往前走x分鐘就好。 直到出現7為止。 【代碼】 #include <bits/stdc++.h&

Codeforces Educational Round 54 Div. 2 A-G

傳送門:cf1076 A. Minimizing the String 貪心刪去第一個字典序大於後一個位置的字母的位置。 #include<bits/stdc++.h> using namespace std; int n; char s[200005];

codeforcesCodeforces Round #523 (Div. 2)

目錄 【B. Views Matter】貪心 【C. Multiplicity】dp+滾動陣列 【D. TV Shows】貪心 【B. Views Matter】  題目連結:https://codeforces.com/contest/1061/problem/B

Codeforces Round #523(Div. 2)TV Shows(貪心+map)

題目連結 D. TV Shows time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The

Codeforces Round #523(Div. 2)Multiplicity(dp)

題目連結 C. Multiplicity time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output

題解codeforces1047A[Codeforces Round #511 (Div. 2)]A.Little C Loves 3 I 數學知識

題目連結 Description Little C loves number «3» very much. He loves all things about it. Now he has a positive integer n. He wants to sp

Codeforces Round 332 (Div 2)A水題A. Patrick and Shopping 遍歷三元環的最小成本

Today Patrick waits for a visit from his friend Spongebob. To prepare for the visit, Patrick needs to buy some goodies in two stores located near his hous

Codeforces Round #416 (Div. 2) A+B

src separate not sum redo swe tput output depend A. Vladik and Courtesy 2 seconds 256 megabytes At regular competition Vl

Codeforces Round #417 (Div. 2) A. Sagheer and Crossroads 模擬 枚舉

ces color 一次 name exit main cst space amp Codeforces Round #417 (Div. 2) A. Sagheer and Crossroads 模擬 枚舉 題意 一個紅綠燈 按逆時針方向一次給出各個路口的左轉,

Codeforces Round #422 (Div. 2) A. I'm bored with life 暴力

out line leave c++ ren round ... from cif A. I‘m bored with life Holidays have finished. Thanks to the help of t

Codeforces Round #306 (Div. 2) A

return code add stl ext scan java pac 一個 題意 給一個字符串(長度<=10^5)。問當中有沒有一個”BA”和一個”AB”呢?假設都有而且它們不反復(即ABA不算),輸出YES。否則輸出NO。 思路 一開