2024.10.11
今日总结:
1:写了2020年csp-s组的第四题贪吃蛇
读完题后考虑分类讨论一共分为两种情况
假设最强蛇为x,最弱蛇为y
- 吃了y不是最弱的蛇牷
- x吃了y之后变成最弱的蛇了
先运行1无法运行时根据2的结果判断是否还能再吃1次最后输出答案。
用两个双端队列q1,q2维护每一次取出最大值和最小值判断。当没办法再运行1时跳至2递归再看一次能否再吃1条
时间复杂度是O(Tn)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int t,n,l1,l2,r1,r2,ans;//ans=被吃了几条蛇
int a[N],q1[N][2],q2[N][2];
struct Node
{
int flag,sum,id;
};
int read()
{
int sum=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum;
}
Node Get_Max()
{
int sum = 0,flag = 1,id = 0;
if(l2 <= r2)
if(q2[r2][0] >= sum)
{
sum = q2[r2][0];
id = q2[r2][1];
flag = 2;
}
if(l1 <= r1)
{
if(q1[r1][0] > sum)
{
sum = q1[r1][0];
id = q1[r1][1];
flag = 1;
}
else if(q1[r1][0] == sum && q1[r1][1] > id)
{
sum = q1[r1][0];
id = q1[r1][1];
flag = 1;
}
}
if(flag == 1) r1 --;
else r2 --;
return (Node){flag,sum,id};
}
Node Get_Min()
{
int sum = 0x7f7f7f7f,flag = 1,id = 0;
if(l2 <= r2)
{
if(q2[l2][0] <= sum)
{
sum = q2[l2][0];
id = q2[l2][1];
flag = 2;
}
}
if(l1 <= r1)
{
if(q1[l1][0] < sum)
{
sum = q1[l1][0];
id = q1[l1][1];
flag = 1;
}
else if(q1[l1][0] == sum && q1[l1][1] < id)
{
sum = q1[l1][0];
id = q1[l1][1];
flag = 1;
}
}
if(flag == 1) l1 ++;
else l2 ++;
return (Node){flag,sum,id};
}
void Solve1()
{
while(1)
{
if(n - ans == 1) return;
Node x = Get_Max(),y = Get_Min();
Node z = Get_Min();
if(x.sum - y.sum > z.sum || (x.sum - y.sum == z.sum && x.id > z.id))
{
ans ++;
q2[-- l2][0] = x.sum - y.sum;
q2[l2][1] = x.id;
if(l1 <= r1 && (z.sum < q1[l1][0] || (z.sum == q1[l1][0] && z.id < q1[l1][1])))
{
q1[-- l1][0] = z.sum;
q1[l1][1] = z.id;
}
else
{
q2[-- l2][0] = z.sum;
q2[l2][1] = z.id;
}
continue;
}
else
{
if(x.flag == 1)
{
q1[++ r1][0] = x.sum;
q1[r1][1] = x.id;
}
else
{
q2[++ r2][0] = x.sum;
q2[r2][1] = x.id;
}
if(z.flag == 1)
{
q1[-- l1][0] = z.sum;
q1[l1][1] = z.id;
}
else
{
q2[-- l2][0] = z.sum;
q2[l2][1] = z.id;
}
if(y.flag == 1)
{
q1[-- l1][0] = y.sum;
q1[l1][1] = y.id;
}
else
{
q2[-- l2][0] = y.sum;
q2[l2][1] = y.id;
}
return;
}
}
}
bool Slove2(int last)
{
if(last == 0) return 0;
if(last == 1) return 0;
if(last == 2) return 1;
Node x = Get_Max();
Node y = Get_Min();
Node z = Get_Min();
if(x.sum - y.sum > z.sum || (x.sum - y.sum == z.sum && x.id > z.id)) return 1;
else
{
if(l1 <= r1 && (z.sum < q1[l1][0] || (z.sum == q1[l1][1] && q1[l1][1] > z.id)))
{
q1[-- l1][0] = z.sum;
q1[l1][1] = z.id;
}
else
{
q2[-- l2][0] = z.sum;
q2[l2][1] = z.id;
}
if(l1 <= r1 && (x.sum - y.sum < q1[l1][0] || (x.sum - y.sum == q1[l1][0] && q1[l1][1] > x.id)))
{
q1[-- l1][0] = x.sum - y.sum;
q1[l1][1] = x.id;
}
else
{
q2[-- l2][0] = x.sum - y.sum;
q2[l2][1] = x.id;
}
return !Slove2(last - 1);
}
}
int main()
{
t = read();
bool flag = 0;
while(t --)
{
ans = 0;
memset(q1,0,sizeof(q1));
memset(q2,0,sizeof(q2));
if(!flag)
{
n = read();
flag = 1;
for(int i = 1;i <= n;i ++)
a[i] = read();
}
else
{
int k = read();
for(int i = 1;i <= k;i ++)
{
int x,y;
x = read();
y = read();
a[x] = y;
}
}
l1 = 1;r1 = 0;l2 = n + 1;
r2 = n;
for(int i = 1;i <= n;i ++)
q1[++ r1][0] = a[i];
for(int i = 1;i <= n;i ++)
q1[i][1] = i;
Solve1();
if(Slove2(n - ans)) ans ++;
cout << n - ans << "\n";
}
return 0;
}
2:复习了线段树和树状数组,并查集,平衡树