8.15 考試反思
T1
P2434 區間
求多個線段的的交。
由題意得,對於任意兩條線段來說,關係有三種:
- 一條在另一條內部,為重合。
- 一條線段和另一條有接觸的部分,稱為相接。
- 一條與另一條完全無接觸部分,稱為相間。
於是可得:
當我們發現兩條線段重合時,捨去較短的一條
如果發現有相接的線段,我們就鎖定相接的線段中較靠右的一條,尋找與之相接的線段,一直下迴圈去
如果發現沒有與當前線段相接的線段,就輸出目前找到的線段的前端和後端,因為這條線段已經到頭了
那麼此題也就出來了,排序+貪心。
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;
}