今天来了一场所谓基础检验的突击测试,虽然这次有2道题之前都做过,但是因为掌握不熟练,导致依旧丢分严重。
T1:特殊排序
氵题一道,用结构体存储,多关键词排序,即可,但我把文件名写错了,100分就这样离我远去;
#include<bits/stdc++.h>
#define ll long long
#define db double
#define re register
#define cs const
using namespace std;
inline int read()
{
int x=0,f=1;
char ch;
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
struct node
{
int num,sum;
}a[10005];
bool cmp(node x,node y)
{
if(x.sum==y.sum) return x.num<y.num;
else return x.sum<y.sum;
}
int l,r,b[10],c[10],top;
int main()
{
//freopen("ssort.in","r",stdin);
//freopen("ssort.out","w",stdout);
l=read();
r=read();
for(int i=l;i<=r;i++)
{
int x=0;
int ii=i;
while(ii)
{
x=x*10+ii%10;
ii/=10;
}
a[++top].sum=x;
a[top].num=i;
}
sort(a+1,a+1+top,cmp);
for(int i=1;i<=top;i++) printf("%d\n",a[i].num);
}
T2:部落卫队
回溯法,用二维数组或邻接表储存关系均可,用一个计数器记录仇敌,但必须加上最优化剪枝,不然会爆,这道题其实是special judge,但教练没加上去,而我的方法是记录最后一次最大的可能,不仅有可能超时,而且前面还有可能WA,所以下次要想到更好的处理方法。
代码:
#include<bits/stdc++.h>
#define ll long long
#define db double
#define re register
#define cs const
using namespace std;
inline int read()
{
int x=0,f=1;
char ch;
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
int n,m,u,v,ans,first[105],net[2*3005],to[2*3005],tot,b[105],d[105],cnt[105],maxn;
void dfs(int now)
{
if(maxn+n-now+1<ans) return;
if(now==n+1)
{
if(maxn>ans)
{
ans=maxn;
for(int i=1;i<=n;i++) d[i]=b[i];
}
return;
}
if(!cnt[now])
{
b[now]=1;
maxn++;
for(int e=first[now];e;e=net[e]) cnt[to[e]]++;
dfs(now+1);
for(int e=first[now];e;e=net[e]) cnt[to[e]]--;
maxn--;
}
b[now]=0;
dfs(now+1);
}
void add(int x,int y)
{
net[++tot]=first[x];
first[x]=tot;
to[tot]=y;
}
int main()
{
//freopen("guard.in","r",stdin);
//freopen("guard.out","w",stdout);
n=read();
m=read();
for(int i=1;i<=m;i++)
{
u=read();
v=read();
add(u,v);
add(v,u);
}
dfs(1);
printf("%d\n",ans);
for(int i=1;i<=n;i++) printf("%d ",d[i]);
return 0;
}
T3:第K大数
一眼暴力,拿了60pts,正解是二分答案,两次二分,首先二分出第k个数,再二分判断它是否为第k个;
代码
#include<bits/stdc++.h>
#define ll long long
#define db double
#define re register
#define cs const
using namespace std;
inline int read()
{
int x=0,f=1;
char ch;
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
int a[10005],b[10005];
int n,m,k,l,r;
int cnt(int x)
{
int ans=0;
for(int i=1;i<=n;i++)
{
int l1=0,r1=m;
while(l1<r1)
{
int mid=(l1+r1+1)/2;
if(a[i]*b[mid]<=x) l1=mid;
else r1=mid-1;
}
ans+=l1;
}
return ans;
}
int main()
{
n=read();
m=read();
k=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=m;i++) b[i]=read();
sort(a+1,a+1+n);
sort(b+1,b+1+m);
l=a[1]*b[1];
r=a[n]*b[m];
while(l<r)
{
int mid=(l+r)/2;
if(cnt(mid)>=k) r=mid;
else l=mid+1;
}
printf("%d",l);
return 0;
}
T4:单词
我们使用AC自动实现。注意要记录单词的出现位置和结束位置,但不能在最后查找,因为单词出现的次数是从它出现的位置开始算起,即所有单词合成的这篇文章中,处于当前单词之前可能还合成了当前单词,但不计入最后结果。
巨佬wyh说还可以用fail反向建边,用fail树来做,因为本人菜鸡,就不再详述
代码:
#include<bits/stdc++.h>
#define ll long long
#define db double
#define re register
#define cs const
using namespace std;
inline int read()
{
int x=0,f=1;
char ch;
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
string s;
vector<int>loc,order;
int n,tri[1000005][26],fail[1000005],tot,cnt[1000005];
void build(string s)
{
int p=0;
int len=s.length();
for(int i=0;i<len;i++)
{
int x=s[i]-'a';
if(!tri[p][x]) tri[p][x]=++tot;
p=tri[p][x];
cnt[p]++;
}
loc.push_back(p);
return;
}
void failure()
{
queue<int>q;
for(int i=0;i<26;i++) if(tri[0][i]) q.push(tri[0][i]);
while(!q.empty())
{
int u=q.front();
order.push_back(u);
q.pop();
for(int i=0;i<26;i++)
{
int x=tri[u][i];
if(!x)
{
tri[u][i]=tri[fail[u]][i];
continue;
}
fail[x]=tri[fail[u]][i];
q.push(x);
}
}
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
cin>>s;
build(s);
}
failure();
for(int i=order.size()-1;i>=0;i--)
{
cnt[fail[order[i]]]+=cnt[order[i]];
}
for(int i=0;i<n;i++)
{
printf("%d\n",cnt[loc[i]]);
}
}
fail树(来自wyh巨佬)
#include<bits/stdc++.h>
using namespace std;
int n;
struct node{
int ch[26],fail,key;
}t[2000003];
int belong[2000003];int cnt;
int first[2000003],nxt[2000003],to[2000003],tot;
void add(int a,int b){
nxt[++tot]=first[a];first[a]=tot;to[tot]=b;
}char ch[2333333];
int l[1000003],r[1000003],key[2000003];
int insert(char s[],int len){
int rt=0;
for(int i=1;i<=len;i++){
if(!t[rt].ch[s[i]-'a']){
t[rt].ch[s[i]-'a']=++cnt;
}rt=t[rt].ch[s[i]-'a'];
t[rt].key++;
}return rt;
}queue<int> q;
void getfail(){
for(int i=0;i<26;i++){
if(t[0].ch[i])q.push(t[0].ch[i]);
}
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
if(t[u].ch[i]){
t[t[u].ch[i]].fail=t[t[u].fail].ch[i];q.push(t[u].ch[i]);
}else{
t[u].ch[i]=t[t[u].fail].ch[i];
}
}
}
}
void query(char s[],int st,int ed){
int rt=0;
for(int i=st;i<=ed;i++){
rt=t[rt].ch[s[i]-'a'];
t[rt].key++;
}
}
void dfs(int u){
key[u]=t[u].key;
for(int i=first[u];i;i=nxt[i]){
int v=to[i];dfs(v);key[u]+=key[v];
}
}
signed main(){
freopen("word.in","r",stdin);
freopen("word.out","w",stdout);
cin>>n;
for(int i=1,L=1,R;i<=n;i++){
scanf("%s",ch+1);int len=strlen(ch+1);belong[i]=insert(ch,len);
}
getfail();
//for(int i=1;i<=cnt;i++)cout<<t[i].fail<<" ";cout<<endl;
//for(int i=1;i<=cnt;i++)cout<<t[i].key<<" ";cout<<endl;
for(int i=1;i<=cnt;i++)add(t[i].fail,i);
dfs(0);
for(int i=1;i<=n;i++){
cout<<key[belong[i]]<<'\n';
}
return 0;
}