8.15 考試反思

adsd45666發表於2024-08-18

8.15 考試反思

T1

P2434 區間

求多個線段的的交。

由題意得,對於任意兩條線段來說,關係有三種:

  1. 一條在另一條內部,為重合。
  2. 一條線段和另一條有接觸的部分,稱為相接。
  3. 一條與另一條完全無接觸部分,稱為相間。

於是可得:

當我們發現兩條線段重合時,捨去較短的一條

如果發現有相接的線段,我們就鎖定相接的線段中較靠右的一條,尋找與之相接的線段,一直下迴圈去

如果發現沒有與當前線段相接的線段,就輸出目前找到的線段的前端和後端,因為這條線段已經到頭了

那麼此題也就出來了,排序+貪心。

AC code:

#include<bits/stdc++.h>
#define seq(q,w,e) for(int q=w;q<=e;q++)
using namespace std;
const int maxn=1e5+10;
struct node{
    int b,e;
}a[maxn];
vector<node> v;
bool cmp(node a,node b){
    if(a.b==b.b) return a.e<b.e;
    return a.b<b.b;
}
int n;
signed main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i].b>>a[i].e;
    }
    sort(a,a+n,cmp);
    v.push_back(a[0]);
    for(int i=1;i<n;i++){
        if(v.back().b<=a[i].b&&v.back().e>=a[i].e)
			continue;
        v.push_back(a[i]);
    }
    int sz=v.size();
	int i=0,j=0;
	while(i<sz){
		j=i; 
		while(v[j].e>=v[j+1].b&&j<sz-1)
			++j;
        cout<<v[i].b<<" "<<v[j].e<<endl;
		i=j+1; 
	} 
    return 0;
}

T2

P2296 尋找道路

一眼 \(BFS\) ,由於邊權為一。(由於沒看限制,喜報20)

由於題目要求必須滿足 \(task1\) 所以,應優先處理 \(task1\) ;

然後就是快樂的 \(BFS\)

預處理:需要先滿足 \(task1\) 的要求,建反圖,執行一個從終點開始 \(BFS\) ,就可以在這張有向圖上處理出所有“可達終點”的結點了。

AC code:

#include<bits/stdc++.h>
#define seq(q,w,e) for(int q=w;q<=e;q++)
using namespace std;
const int maxn=1e4+10,maxm=2e5+10;
int n,m,st,ed;
int deg[maxn];
vector<int> tow_G[maxn],rev_G[maxn];
bool vis[maxn];
queue<int> q;
void BFS(){
	cin>>n>>m;
	for(int i=1;i<=m;++i){
		int u,v; scanf("%d%d",&u,&v);
		tow_G[u].push_back(v); 
		rev_G[v].push_back(u);
	}
	cin>>st>>ed;
	q.push(ed);
	while(!q.empty()){
		int tmp=q.front(); q.pop();
		if(vis[tmp]) continue; vis[tmp]=true;
		for(int i=0;i<rev_G[tmp].size();++i){
			int j=rev_G[tmp][i];
			deg[j]++;
			q.push(j);
		}
	}
}
int dis[maxn];
void s_BFS(){
	memset(vis,0,sizeof(vis));
	memset(dis,0x3f,sizeof(dis)); 
	dis[st]=0;
	q.push(st);
	while(!q.empty()){
		int tmp=q.front(); q.pop();
		if(vis[tmp]) continue; vis[tmp]=true;
		if(deg[tmp]!=tow_G[tmp].size()) continue;
		for(int i=0;i<tow_G[tmp].size();++i){
			int j=tow_G[tmp][i];
			if(dis[j]>dis[tmp]+1){
				dis[j]=dis[tmp]+1;
				q.push(j);	
			}
		}
	}
}
int main(){
    // ios::sync_with_stdio(false);cin.tie(0);
    BFS();
    s_BFS();
    cout<<(dis[ed]!=0x3f3f3f3f?dis[ed]:-1);
    return 0;
}

T3

看的不是很懂,引用一下題解(QAQ)。

用遞推,推一下遞推式子。

\(n\) 個物品中取 \(m\) 個物品,若不取這個物品,則從 \(n-1\)\(m\) 推過來,若取這個物品則從 \(n-1\)\(m-1\) 推過來。

所以 \(f[i][j]=f[i-1][j-1]+f[i-1][j]\)

AC code:

#include<bits/stdc++.h>
#define seq(q,w,e) for(int q=w;q<=e;q++)
#define ll long long
using namespace std;
const int maxn=2011;
ll f[maxn][maxn];
ll h[maxn],l[maxn]; 
ll ff[maxn][maxn];
ll n,m,k,t,i,j;
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>t>>k;
    f[0][0]=1;
    for (i=1;i<=2001;i++){   
        f[i][0]=1;
        for (j=1;j<=i;j++){
            f[i][j]=(f[i-1][j-1]+f[i-1][j])%k;
            if (f[i][j]==0){
                h[i]++;
            }
            ff[i][j]=ff[i-1][j]+h[i];
            if (j==i) ff[i][j]=h[i]+ff[i-1][j-1];
        }
    }
    while (t--){
        cin>>n>>m;
        if (m>n) m=n;
        cout<<ff[n][m]<<"\n";
    }
    return 0;
}

相關文章