NOIP模拟81
T1 语言
解题思路
模拟即可,对于一个合法的句子直接判断每一个前缀和每一个后缀是否是合法的名词词组。
然后枚举动词的位置判断前后两段是否合法就好了。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigend long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();};
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10;
int T,n,s[30];
char ch[N];
bool can1[N],can2[N];
inline bool juda(int x){return x&1;}
inline bool judn(int x){return x&2;}
inline bool judv(int x){return x&4;}
void solve()
{
for(int i=0;i<26;i++) s[i]=read();
scanf("%s",ch+1); n=strlen(ch+1);
for(int i=1;i<=n;i++) can1[i]=can2[i]=false;
for(int i=1;i<=n;i++)
if(!juda(s[ch[i]-'a'])&&!judn(s[ch[i]-'a'])) break;
else if(judn(s[ch[i]-'a'])) can1[i]=true;
if(judn(s[ch[n]-'a']))
for(int i=n;i>=1;i--)
if(!juda(s[ch[i]-'a'])&&!judn(s[ch[i]-'a'])) break;
else can2[i]=true;
for(int i=2;i<n;i++)
if(judv(s[ch[i]-'a'])&&can1[i-1]&&can2[i+1])
return printf("Yes\n"),void();
printf("No\n");
}
#undef int
int main()
{
#define int long long
freopen("language.in","r",stdin); freopen("language.out","w",stdout);
T=read(); while(T--) solve();
return 0;
}
T2 色球
解题思路
复杂度可以达到 \(\mathcal{O}(n)\) 用链表实现标记是否反转即可。。
当然我比较懒,暴力做法+双端队列启发式合并复杂度就是 \(\mathcal{O}{nlogn}\) 的了。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigend long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();};
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=2e5+10;
int n,m,id[N],rev[N];
deque<pair<int,int> > q[N];//col,sum
char opt[10];
inline void insert_front(int sum,int col,int x)
{
if(!q[x].size()) q[x].push_back(make_pair(col,sum));
else if(q[x].back().first==col){sum+=q[x].back().second;q[x].pop_back();q[x].push_back(make_pair(col,sum));}
else q[x].push_back(make_pair(col,sum));
}
inline void insert_back(int sum,int col,int x)
{
if(!q[x].size()) q[x].push_front(make_pair(col,sum));
else if(q[x].back().first==col){sum+=q[x].front().second;q[x].pop_front();q[x].push_front(make_pair(col,sum));}
else q[x].push_front(make_pair(col,sum));
}
inline void insert(int sum,int col,int x)
{
if(!rev[x]) insert_front(sum,col,x);
else insert_back(sum,col,x);
}
inline void move_front(int x,int y)
{
for(int sum=0;sum<y;)
{
pair<int,int> temp=q[x].back(); q[x].pop_back();
if(temp.second<y-sum){sum+=temp.second;continue;}
temp.second-=y-sum; q[x].push_back(temp);
return printf("%lld\n",temp.first),void();
}
}
inline void move_back(int x,int y)
{
for(int sum=0;sum<y;)
{
pair<int,int> temp=q[x].front(); q[x].pop_front();
if(temp.second<y-sum){sum+=temp.second;continue;}
temp.second-=y-sum; q[x].push_front(temp);
return printf("%lld\n",temp.first),void();
}
}
inline void move(int x,int y)
{
if(!rev[x]) move_front(x,y);
else move_back(x,y);
}
inline void merge_work(int x,int y)
{
if(!rev[x]) while(!q[x].empty()) insert(q[x].back().second,q[x].back().first,y),q[x].pop_back();
else while(!q[x].empty()) insert(q[x].front().second,q[x].front().first,y),q[x].pop_front();
}
inline void merge(int &x,int &y)
{
if(q[x].size()<q[y].size()) merge_work(x,y);
else merge_work(y,x),swap(x,y),rev[y]^=1;
}
#undef int
int main()
{
#define int long long
freopen("color.in","r",stdin); freopen("color.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=n;i++) id[i]=i;
while(m--)
{
int x,y,z; scanf("%s",opt+1); x=read(); y=read();
if(strlen(opt+1)==4) z=read(),insert(x,y,id[z]);
else if(opt[2]=='o') move(id[y],x);
else merge(id[x],id[y]);
}
return 0;
}
T3 斐波
大坑未补
T4 偶数
KMP 求最长 boder
可以得到 40pts (code)