NOIP模拟1
A. 语言
想到小学英语老师一遍遍地强调:每个句子有且只有一个动词!!忽然给了我灵感。发现不是动词的部分AN可以自由组合,A可以这样连续A(AN),A(A(AN)),唯一不合法的情况就是A在末尾,也就是V分出来的前后两段中末尾只要有可能是N就Yes,判断一下就好了。
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 3;
char s[maxn];
int T, n, zm[30], cnt, pos;
bool flag;
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;
}
int main()
{
freopen("language.in", "r", stdin);
freopen("language.out", "w", stdout);
T = read();
while(T--)
{
for(int i=1; i<=26; i++)
{
zm[i] = read();
}
flag = 0; cnt = 0; pos = 0;
scanf("%s", s+1); n = strlen(s+1);
if(!(zm[s[n]-'a'+1] & 2))
{
printf("No\n"); continue;
}
for(int i=1; i<=n; i++)
{
if(zm[s[i]-'a'+1] == 4) cnt++, pos = i;
}
if(cnt > 1 || pos == 1)
{
printf("No\n"); continue;
}
if(pos)
{
if(zm[s[pos-1]-'a'+1] & 4) printf("Yes\n");
else printf("No\n");
}
else
{
for(int i=2; i<n; i++)
{
if((zm[s[i]-'a'+1] & 4) && (zm[s[i-1]-'a'+1] & 2))
{
flag = 1; printf("Yes\n"); break;
}
}
if(!flag) printf("No\n");
}
}
return 0;
}
B. 色球
->思考怎么写链表遇到了两个问题:
1.每一个链表大小开maxn,有maxn个位置,会MLE
sol:链表占用的内存和是maxn,链表结构体只需要一个,其实这个和邻接链表存图很相似
2.链表分为pre和nxt,一会走pre一会走nxt判断起来太复杂
sol:双向链表都是中间pre和nxt都满着,两边空一个,用满的填空的来合并,从端点开始找满的那个是单向的
process:
无限容器,盲猜vector都会炸,所以搞了个什么回退把空间复杂度降到了O(n),结果还不如写个暴力呢。。
我居然都没有写个暴力保底。。考试策略差评
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 3;
int n, m, ans;
typedef pair<int, int> pii;
vector<pii> ve[maxn];
char op[7];
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;
}
int main()
{
freopen("color.in", "r", stdin);
freopen("color.out", "w", stdout);
n = read(); m = read();
while(m--)
{
scanf("%s", op);
if(op[2] == 's')
{
int x = read(), y = read(), z = read();
ve[z].push_back(pii(x, y));
}
else if(op[2] == 't')
{
int u = read(), v = read();
int sz = ve[u].size();
for(int x=sz-1; x>=0; x--)
{
ve[v].push_back(ve[u][x]);
}
ve[u].clear();
}
else
{
int x = read(), z = read();
while(x)
{
if((*--ve[z].end()).first < x)
{
x -= (*--ve[z].end()).first;
ve[z].erase(--ve[z].end());
}
else
{
ans = (*--ve[z].end()).second;
(*--ve[z].end()).first -= x;
if((*--ve[z].end()).first == 0) ve[z].erase(--ve[z].end());
break;
}
}
printf("%d\n", ans);
}
}
return 0;
}
为什么用链表比用vector优化?空间上:复制消耗的空间不存在了,直接操作
时间上,复制花费的循环不存在了,,所以最麻烦的操作就在于反向复制了?怪不得没有“不含询问3”的特殊数据
不过用数组模拟链表的话,用不了的内存还是要开满???那不就&*%¥#@*……
但是如果只记录前驱后继,那又一定会丢失信息,所以每个“点”都需要详细信息
对每个位置开链表不一定分的那么清楚,连tot和箭头数组都要分开,一个就够了
在没有方向不变的时候,ch[0]代表靠近tail的上一个,ch[1]代表靠近head的上一个,
反向的过程,让下一个成为head,而原来的表尾只存在ch[1],那就只能跳ch[1],在跳的方向上删掉自己
导致下一个也只有一个选择,每个起点都一定只有一个选择
连续反向就导致ch[0]和ch[1]的灵活互换,双向链表正反来回变,可以解释为什么不直接在正向时填入ch[0]反向时填入ch[1]
那么所以为什么新点没有分类讨论??
既然它没有讨论,那是不是就说明下文的比较也不重要??
不是,新节点的ch肯定都是空的,这就是不分讨的理由!!
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 3;
int n, m, tot, h[maxn], t[maxn];
char op[7];
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;
}
struct line
{
int c, num, ch[2];
}p[maxn];
int main()
{
freopen("color.in", "r", stdin);
freopen("color.out", "w", stdout);
n = read(); m = read();
for(int i=1; i<=m; i++)
{
scanf("%s", op);
if(op[2] == 's')
{
int x = read(), y = read(), z = read();
p[++tot] = (line){y, x, h[z], 0};
if(h[z]) p[h[z]].ch[0] ? (p[h[z]].ch[1] = tot) : (p[h[z]].ch[0] = tot);
else t[z] = tot;
h[z] = tot;
}
else if(op[2] == 'p')
{
int x = read(), y = read();
while(p[h[y]].num < x)//猜对了,h等于0了,死循环了!!!
{
//printf("h[%d] = %d\n", y, h[y]);
//printf("x = %d\n", x);
if(!h[y]) exit(0);
x -= p[h[y]].num;//另一个新发现是x=4之后再也不减小了??
int nxt = p[h[y]].ch[0] | p[h[y]].ch[1];
if(nxt)
{
//找到错因了:比较的是下一个,删的也是下一个,我怎么删成自己了?!
p[nxt].ch[0] == h[y] ? (p[nxt].ch[0] = 0) : (p[nxt].ch[1] = 0);
}
h[y] = nxt;//这个写在外面,似乎也不重要因为保证了不合法情况不存在
}
p[h[y]].num -= x;
printf("%d\n", p[h[y]].c);
}
else
{
int x = read(), y = read();
if(!h[x]) continue;
if(h[y])
{
p[h[y]].ch[0] ? (p[h[y]].ch[1] = h[x]) : (p[h[y]].ch[0] = h[x]);
p[h[x]].ch[0] ? (p[h[x]].ch[1] = h[y]) : (p[h[x]].ch[0] = h[y]);
}
else t[y] = h[x];
h[y] = t[x];//t[y] = h[x]我憨了,顺序没了
h[x] = t[x] = 0;
}
}
return 0;
}
时光花火,水月星辰