2018.10.11模擬賽
阿新 • • 發佈:2018-12-14
T1
一道類似貪心的模擬題,就是要刪除一些讓最大
可以先存兩個結構體,一個按排序,一個按排序,然後列舉中刪掉幾個,看相應的中最多能刪掉幾個
首先裡刪掉個的時候,中一定可以刪掉個,不斷往後刪除,如果它刪的那個矩形在中的位置在前個,那它就不用再在中刪除了,就這樣用兩個指標維護一下就好了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include <cstring>
#include<cmath>
#define maxn 100005
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
int t,n,m,pos[maxn],vis[maxn],cas;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c= getchar();
return x*f;
}
struct qwq{
int a,b,id;
bool operator <(const qwq &x) const{
return a<x.a||(a==x.a&&b<x.b);
}
}tra[maxn],trb[maxn];
inline bool cmp(qwq x,qwq y){return x.b<y.b||(x.b==y.b&&x.a<y.a);}
int main(){
freopen("d.in","r",stdin);
freopen ("d.out","w",stdout);
t=rd();
while(t--){
n=rd(); m=rd(); cas++;
for(int i=1;i<=n;i++)
tra[i].a=rd(),tra[i].b=rd(),tra[i].id=i,
trb[i].a=tra[i].a,trb[i].b=tra[i].b,trb[i].id=i;
sort(tra+1,tra+n+1); sort(trb+1,trb+n+1,cmp);
for(int i=1;i<=n;i++)
pos[trb[i].id]=i;
int l=0,r=m+1,mna=0,mnb=0;
LL ans=1LL*tra[1].a*trb[r].b;
for(int i=1;i<=m;i++){
if(pos[tra[i].id]<r) vis[pos[tra[i].id]]=cas;
else{
r--;
while(vis[r]==cas) r--;
}
ans=max(ans,1LL*tra[i+1].a*trb[r].b);
}
printf("%lld\n",ans);
}
return 0;
}
T2
這個題其實有很多種方法可以過掉,給的好像是狀壓,然後有人還用狀壓過掉
但是!我用的是優秀的!這真是暴力拍標算的例項啊
可以發現如果點度都是偶數那麼一定可以一遍走到,因此只要把所有度數為奇的點拿出來兩兩匹配,邊的長度就是他們的最短路,用之前所有的邊的長度加上最小的兩兩配對的邊長度就是答案
然後可以用各種各樣的姿勢和小剪枝來優化
實測比快
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 25
#define M 1005
#define inf 0x3f3f3f3f
using namespace std;
int n,m,ans,f[N][N],d[N];
int nw[N],tot,val[N][N],res=inf;
bool vis[N];
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
inline void dfs(int now,int sum,int t){
if(t==tot/2){
res=min(res,sum);
return;
}
if(res<=sum) return;
if(vis[now]) {
dfs(now+1,sum,t); return;
}
vis[now]=1;
for(int i=now+1;i<=tot;i++)
if(!vis[i]){
vis[i]=1;
dfs(now+1,sum+val[now][i],t+1);
vis[i]=0;
}
vis[now]=0;
return;
}
int main(){
freopen("jogging.in","r",stdin);
freopen("jogging.out","w",stdout);
n=rd(); m=rd(); memset(f,0x3f,sizeof f);
for(int i=1;i<=m;i++){
int x=rd(),y=rd(),z=rd(); d[x]++,d[y]++;
ans+=z; f[x][y]=f[y][x]=min(f[x][y],z);
}
for(int i=1;i<=n;i++) f[i][i]=0;
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
for(int i=1;i<=n;i++)
if(d[i]&1)
nw[++tot]=i;
for(int i=1;i<=tot;i++)
for(int j=i+1;j<=tot;j++)
val[i][j]=val[j][i]=f[nw[i]][nw[j]];
dfs(1,0,0);
printf("%d\n",ans+res);
return 0;
}
/*
4 6
1 2 3
2 3 4
3 4 5
1 4 10
1 3 12
2 4 8
*/
T3
毒瘤題···
題解說的很清晰了
具體實現看程式碼註釋吧,還是挺難寫的,綜合了樹,,二分答案···
總之是一道考驗程式碼能力的好題咯
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define prit pair<LL,LL>
#define mp make_pair
#define fi first
#define se second
#define N 500005
#define K 35
#define M N*31
#define LL long long
using namespace std;
int n,k,a[N],trie[M][2],tot=1,siz[M];
LL val0[K],val1[K],p;
vector< prit > vec1,vec2;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
inline void insert(int x){
int now=1;
for(int i=k-1;i>=0;i--){
++siz[now];
if((x>>i)&1)//這一位是1
val1[i]+=siz[trie[now][0]];
else val0[i]+=siz[trie[now][1]];
if(!trie[now][(x>>i)&1]) now=trie[now][(x>>i)&1]=++tot;
else now=trie[now][(x>>i)&1];
}
++siz[now];
}
inline bool check(prit lim){
LL res=0;//雙指標
for(int i=0,j=vec2.size()-1;i<vec1.size();i++){
while(j>=0 && mp(vec1[i].fi+vec2[j].fi,vec1[i].se|vec2[j].se)>lim)
j--;//將前一半和後一半合併
res+=j+1;
}
return res>=p;
}
signed main(){
freopen("f.in","r",stdin);
freopen("f.out","w",stdout);
n=rd(); k=rd(); scanf("%lld",&p);
for(int i=1;i<=n;i++){
a[i]=rd(); insert(a[i]);//插入01trie
}
int k1=k/2,k2=k-k1;//meet in the middle
for(int i=0;i<(1<<k1);i++){
LL tmp=0;
for(int j=0;j<k1;j++)
if((i>>j)&1) tmp+=val1[j];
else tmp+=val0[j];
vec1.push_back(mp(tmp,i));
}
for(int i=0;i<(1<<k2);i++){
LL tmp=0;
for(int j=0;j<k2;j++)
if((i>>j)&1) tmp+=val1[j+k1