前四题有多顺利E题就有多痛苦。
#include
using namespace std;
typedef long long ll;
typedef pair pii;
void solve()
{
string x;
cin>>x;
int mn=10;
for(int i=0;i>t;
while(t--)
{
solve();
}
return 0;
}
这个还是贪心,观察可得要找的这个数字y就是数字x里最小的数字。那就可以考虑将数字x以字符串的形式读入,然后遍历一遍求每位数字的最小值即可。
#include
using namespace std;
typedef long long ll;
typedef pair pii;
void solve()
{
int n,k;
cin>>n>>k;
vectora(n);
for(int i=0;i>a[i];
}
int cnt=0;
for(int i=0,j=0;i>t;
while(t--)
{
solve();
}
return 0;
}
这个题就是纯模拟,没啥好说的。
代码就是双指针往后滑,每次先让指针i来到数值是0的位置,即好天气,然后让指针j往后滑完这个全0区间。借着每次检查一下这个区间长度是否够了k,够了就统计答案即可。
#include
using namespace std;
typedef long long ll;
typedef pair pii;
void solve()
{
int n,ini;
cin>>n>>ini;
vectora(n+1);
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
int pos=a[ini];
sort(a.begin()+1,a.end());
int start=0;//当前下标
for(int i=1;i<=n;i++)
{
if(a[i]==pos)
{
pos++;
start=i;
break;
}
}
int level=1;
for(int i=start;i>t;
while(t--)
{
solve();
}
return 0;
}
这个题其实也是纯模拟。
观察可以发现,其实原来的顺序并没有意义,那么可以考虑先对塔从小到大排序,这样就可以从低一步一步往高处跳了。之后的思路就是纯模拟,观察可以发现,即使可以一步跳得更高,那么同样可以一步一步按顺序跳。那就是每次算出往上跳一个的蓄力时间和死亡时间,只有死亡时间比蓄力时间长才能活。
因为需要排序,所以得先用pos记一下初始的高度,然后排序,再遍历一遍找到排序后所在的下标,后面只需要从这开始即可。之后设置变量level表示水位,然后计算还有多久死亡die和蓄力时间time。所以死亡时间的公式就是当前高度减去水位高度加一,蓄力时间就是下一步的高度减当前高度。如果一旦发现死亡时间小于等于蓄力时间,那么直接输出no,否则就更新当前位置pos和水位level即可。
#include
using namespace std;
typedef long long ll;
typedef pair pii;
void solve()
{
ll n,k;
cin>>n>>k;
vector>a(n+1,vector(3));
for(int i=1;i<=n;i++)
{
cin>>a[i][0]>>a[i][1]>>a[i][2];
}
sort(a.begin()+1,a.end(),[&]
(const vector&x,const vector&y){
return x[0]>t;
while(t--)
{
solve();
}
return 0;
}
这个题其实也是贪心。
思路就是先对赌场按进入限制从小到大排序,接着每次先把能进的所有赌场抓出来。因为这里的钱数是直接更改后的钱数,所以对于一个有最大的钱数的赌场,即使还有很多比它小的钱数的赌场,不管去不去,去几个比最大钱数小的赌场,最后都需要去这个最大钱数的赌场把钱更新为这个最大值。所以只需要去一次这个最大钱数的赌场即可,那就是每次统计进去赌完了的钱数的最大值。之后,假如这个最大值能把当前的钱数更新得更大,那么就可以去赌场赚钱,然后去后续解锁的赌场玩。如果发现最大值都不比当前钱大,那当前就是能达到的最大钱数,后续就不玩了直接返回。
#include
using namespace std;
typedef long long ll;
typedef pair pii;
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
void solve()
{
int n;
cin>>n;
vectorp(n+1);
for(int i=1;i<=n;i++)
{
cin>>p[i];
}
vectors(n+1);
for(int i=1;i<=n;i++)
{
cin>>s[i];
}
//易得p[i]=gcd(p[i-1],a[i]) s[i]=gcd(s[i+1],a[i])
//所以p[i]可以整除a[i],s[i]可以整除a[i] -> p[i]|a[i],s[i]|a[i] -> a[i]里包含p[i]和s[i]的质因子幂
//所以lcm(p[i],s[i])可以整除a[i]
//假设存在一个质数k,使得a[i]也能被k*lcm整除 -> a[i]里会有lcm里没有的质因子幂
//所以k不能被p[i-1]和s[i+1]整除 -> p[i-1]和s[i+1]不包含额外的质因子
//所以直接可以在a[i]里去掉质因子k,使a[i]直接为lcm(p[i],s[i])
//所以只需要先让a[i]为lcm(p[i],s[i]),再check前后缀是否合法即可
vectora(n+1);
for(int i=1;i<=n;i++)
{
a[i]=lcm(p[i],s[i]);
}
ll x=a[1];
for(int i=1;i<=n;i++)
{
x=gcd(x,a[i]);
if(x!=p[i])
{
cout<<"NO"<=1;i--)
{
x=gcd(x,a[i]);
if(x!=s[i])
{
cout<<"NO"<>t;
while(t--)
{
solve();
}
return 0;
}
赛时拼尽全力没想到lcm……
赛时其实想到了p[i]等于gcd(p[i-1],a[i])和s[i]等于gcd(s[i+1],a[i])这个结论,所以根据唯一分解定理,抽象一点理解,p[i]和s[i]一定是a[i]分解后的一部分。那么可以得到p[i]和s[i]可以整除a[i],所以一定有lcm(p[i],s[i])可以整除a[i]。那么就存在一个质数k,使得a[i]也可以被k*lcm(p[i],s[i])整除,因为a[i]里一定有p[i]和s[i]中没有的质因子幂。所以,k就不能被p[i-1]和s[i+1]整除,因为这俩里不包含k这个额外的质因子。所以在构造a[i]时,可以直接令a[i]等于lcm(p[i],s[i])即可。
所以之后的思路就是先构造数组a,让a[i]就等于lcm。然后再分别遍历数组p和数组s,检验这个a[i]是否满足p[i]和s[i]的要求即可。
#include
using namespace std;
typedef long long ll;
typedef pair pii;
typedef pairpll;
const int MAXN=2e5+5;
//不能每次遍历所有边 -> 菊花图
//考虑对每个节点建立一张map
//存到其孩子节点的每种颜色的代价和
//每次考察更改节点的父亲和自己的map即可
void dfs(int u,int father,
vector>&g,vector&color,vector&fa,vector&sums,vector
这思路太逆天了……
多少得学一下lambda表达式了,多样例测试开全局变量就得每次清空,不全局写函数又得全传进去,关键这个题把query单独写成一个函数还会TLE……
首先,上来第一反应肯定是每次考察修改的点的每条边。但再思考可以发现,假如这是一个菊花图,那么每次都考察所有边的时间复杂度太高了,肯定过不去。那么就需要设计一种结构,使得每次修改的时间是O(1)的。
先考虑对每一个节点建立一张map,存其所有孩子节点中,每种颜色对应的代价之和。那么思路就是当修改节点u时,去只需要考察节点u的父亲节点和所有孩子节点即可。那么除了这张map,还需要建立fa数组存每个节点的父节点,wf数组存每个节点去其父节点的代价,以及sums数组存每个节点到其所有孩子节点的代价之和。有了这些信息,那么对于每个要修改的节点u,可以先扣掉其原本的代价,然后修改颜色,再加上修改后的代价。这样就实现了每次修改的时间是O(1)的。
所以就是上来先dfs一遍初始化所有信息。如果和父节点不同色,那么需要把代价加到ans里,同时构建fa数组,wf数组,sums数组和sumColor这张map。
之后处理每个query,如果修改了颜色,那么需要先把更新前的代价都扣掉。首先,如果和父节点的颜色不同,需要先从ans里扣掉到父节点的代价。之后处理孩子节点,设置diff表示颜色不同的代价和。那么diff就是所有孩子节点的代价和sums减去颜色相同的代价和sumColor,最后让ans减去diff即可。如果有父节点的话,需要再扣掉父节点的sumColor中当前节点颜色的代价。
之后修改颜色,更新color数组,然后更新父节点的sumColor中修改后颜色的代价。
最后把修改后的代价加回来,那就是如果修改后的颜色和父节点不同,就先往ans里加上去父节点的代价。然后,首先让ans加上去所有孩子节点的代价和,再减去和修改后颜色相同的代价和即可。最后每次都输出ans即可。
数论和图论永远的痛……