2019年8月5日(NOIP模拟赛DAY1)
作者:互联网
又爆零了!! T_T……
prob1:同花顺(\(card\))
傻逼题竟然没写出来,郁闷……
考虑以卡牌\(i\)为同花顺的结尾,则肯定会换的卡牌数为\(num=\sum[b_j<b_i-n+1]+\sum[a_j \ne a_i \land b_j>=b_i-n+1 \land b_j<=b_i]+\sum[b_j>b_i]\).
好吧,看到柿子就不想做了……
但其实,若用补集思想考虑一波就可以化为\(num=n-\sum[a_j=a_i \land b_j>=b_i-n+1 \land b_j<=b_i]\).
这样柿子就有好多了呢……
再已颜色为第一关键字,牌号为第二关键字进行排序,就可以做到十分优秀的循环剪枝\(break\),去除了不少的不必要操作,复杂度从\(O(n^2)\)变成了\(O\)(能过),相当优秀。
最后补一句:记得去重。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define fdr(i,a,b) for(int i=a;i>=b;--i)
#define int long long
#define jinitaimei signed
inline int read()
{
int x=0,f=1;char ch=getchar();
for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x*f;
}
const int xx=1e5+10;
struct prom{int c,n;}b[xx],a[xx];
inline bool cmp(prom x,prom y){return (x.c^y.c)?(x.c<y.c):(x.n<y.n);}
jinitaimei main()
{
int n=in,cnt=0;
fur(i,1,n) a[i]=(prom){in,in};
sort(a+1,a+n+1,cmp);
fur(i,1,n)
{
while(a[i].c==a[i+1].c&&a[i].n==a[i+1].n) ++i;
b[++cnt]=a[i];
}
int ans=0;
fur(i,1,cnt)
{
int tmp=0;
fdr(j,i,1)
{
if(b[j].c==a[i].c&&b[j].n>=a[i].n-n+1) ++tmp;
else break;
}
ans=max(ans,tmp);
}
printf("%lld\n",n-ans);
return 0;
}
prob2:做实验(\(test\))
枚举数\(a\)的每个子集,询问其最后出现的时间是否在\(i-b\)与\(i-1\)之间,若是,则有一点贡献,同时更新该子集的最后出现时间。
\(30\)分部分分,暴力枚举所有小于等于\(a\)的数\(i\),判断其是否是\(a\)的子集,然后进行累加贡献:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define in read()
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define int long long
#define jinitaimei signed
inline int read()
{
int x=0,f=1;char ch=getchar();
for(;!isalnum(ch);ch=getchar()) if(ch=='-') f=-1;
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x*f;
}
const int xx=1e5+10;
int f[xx];
jinitaimei main()
{
int n=in;
fur(i,1,n)
{
int x=in,y=in,res=0;
fur(j,1,x)
{
if((j|x)!=x) continue;
if(f[j]<i-y) ++res;
f[j]=i;
}
printf("%lld\n",res);
}
return 0;
}
正解 :使用按位与&枚举子集(自己推一下就好了):
#include<bits/stdc++.h>
using namespace std;
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define fdr(i,a,b) for(int i=a;i>=b;--i)
#define in read()
#define int long long
#define jinitaimei signed
inline int read()
{
int x=0;
char ch=getchar();
for(;!isalnum(ch);ch=getchar());
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x;
}
const int xx=1e5+10;
int las[xx];
jinitaimei main()
{
int n=in;
fur(i,1,n)
{
int a=in,b=in,res=0;
for(int j=a;j;j=(j-1)&a)
{
if(las[j]<i-b) ++res;
las[j]=i;
}
printf("%lld\n",res);
}
return 0;
}
貌似标码比暴力还短??
prob3:拯救世界(\(save\))
思路清晰:\(Tarjan\)缩点+\(spfa\)最长路,最后枚举终点取\(max\)即可。
(貌似\(Tarjan\)写丑了):
#include<bits/stdc++.h>
using namespace std;
#define fur(i,a,b) for(int i=a;i<=b;++i)
#define fdr(i,a,b) for(int i=a;i>=b;--i)
#define int long long
#define jinitaimei signed
#define pi pair<int,int>
#define nm make_pair
#define in read()
inline int read()
{
int x=0,k=1;
char ch=getchar();
for(;!isalnum(ch);ch=getchar()) k=(ch=='-'?-1:1);
for(;isalnum(ch);ch=getchar()) x=x*10+ch-'0';
return x*k;
}
const int xx=5e5+10;
int sta[xx],top=0,all=0;
int low[xx],id[xx],cnt=0;
int sum[xx],w[xx];
int bel[xx],bar[xx];
int u[xx],v[xx],dis[xx];
bool vis[xx],viss[xx];
vector<int>e[xx];
vector<pi>f[xx];
deque<int>p;
inline void Tarjan(int g)
{
low[g]=id[g]=++cnt;
sta[++top]=g;
vis[g]=true;
fur(i,0,(int)e[g].size()-1)
{
if(!id[e[g][i]])
{
Tarjan(e[g][i]);
low[g]=min(low[g],low[e[g][i]]);
}
else if(vis[e[g][i]]) low[g]=min(low[g],id[e[g][i]]);
}
if(id[g]==low[g])
{
++all;
do
{
int tp=sta[top];
sum[all]+=w[tp];
vis[tp]=false;
bel[tp]=all;
}while(sta[top--]!=g);
}
}
inline void spfa(int g)
{
fur(i,1,all) dis[i]=0,viss[i]=false;
int s=bel[g];
p.push_back(s);
dis[s]=sum[s];
viss[s]=true;
while(!p.empty())
{
int hd=p.front();
p.pop_front();
viss[hd]=false;
fur(i,0,(int)f[hd].size()-1)
{
if(f[hd][i].second+dis[hd]>dis[f[hd][i].first])
{
dis[f[hd][i].first]=dis[hd]+f[hd][i].second;
if(!viss[f[hd][i].first])
{
viss[f[hd][i].first]=true;
if(!p.empty())
{
if(dis[f[hd][i].first]>dis[p.front()]) p.push_front(f[hd][i].first);
else p.push_back(f[hd][i].first);
}
else p.push_back(f[hd][i].first);
}
}
}
}
}
jinitaimei main()
{
int n=in,m=in;
fur(i,1,m)
{
u[i]=in,v[i]=in;
if(u[i]==v[i]) continue;
e[u[i]].push_back(v[i]);
}
fur(i,1,n) w[i]=in;
fur(i,1,n) if(!id[i]) Tarjan(i);
fur(i,1,m) if(bel[u[i]]!=bel[v[i]]) f[bel[u[i]]].push_back(nm(bel[v[i]],sum[bel[v[i]]]));
int s=in,p=in;
fur(i,1,p) bar[i]=in;
spfa(s);
int ans=0;
fur(i,1,p) ans=max(ans,dis[bel[bar[i]]]);
printf("%lld\n",ans);
return 0;
}
标签:ch,fur,NOIP,int,DAY1,xx,2019,hd,define 来源: https://www.cnblogs.com/ALANALLEN21LOVE28/p/11313034.html