有一朵花初始1厘米高,给出n天是否浇水的情况。要求求出最后花朵的高度
如果花朵死亡,则返回-1
按照题意模拟即可
#include
using namespace std;
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
int n;cin>>n;
int pre = -1;
int cur = 1;
int die = 0;
for (int i=1;i<=n;++i)
{
int sta;cin>>sta;
if (sta==0&&pre==0)
die = 1;
else if (sta==1&&pre==1)
cur+=5;
else if (sta==1)
cur+=1;
pre = sta;
}
if (die)cout<<"-1\n";
else cout<
给一个长为n的数组a
定义转置操作:
选取数字 a n a_n an,将数组a中所有 ≤ a n \le a_n ≤an的数字放在左边
所有 ≥ a n \ge a_n ≥an的数字放在右边
两边数字与数字之间原本的顺序保持不变
换句话说,转置操作是稳定的
要求你计算,在第几次之后的转置操作不会再改变数组a
如果 a n a_n an为最大值的话,那就不可能改变数组a了
因此,我们要计算过了几次之后 a n a_n an会变成最大值
按照稳定的排序的想法,进行一次转置操作之后,新的 a n a_n an是距离原本 a n a_n an最近的
第一个大于他的值
#include
using namespace std;
const int maxn = 2e5+100;
int a[maxn];
int n;
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
cin>>n;
for (int i=1;i<=n;++i)cin>>a[i];
int cur = a[n];
int ans = 0;
for (int i=n-1;i>=1;--i)if (a[i]>cur)
{
++ans;
cur = a[i];
}cout<
数轴上,坐标0处有 n n n个货物
坐标轴上有 n n n个仓库,你要给每个仓库分配一个货物
刚开始你在坐标0上,你一次最多可以拿 k k k个货物,请问你最短需要走多远的路?
不要求最后返回坐标0
先不考虑负轴。
对于仓库 1 , 2 , 3 , 4 , 5 1,2,3,4,5 1,2,3,4,5
k = 2 k=2 k=2
一个贪心的想法是,我们先填 1 , 2 1,2 1,2再填 3 , 4 3,4 3,4,然后最后单独填 5 5 5
这样的花费为: 2 × 2 + 2 × 4 + 5 = 17 2\times 2+2\times 4+5=17 2×2+2×4+5=17
很明显,有更好的策略
我们可以:先填 1 1 1,再填 2 , 3 2,3 2,3,最后填 4 , 5 4,5 4,5
花费为: 2 × 1 + 2 × 3 + 5 = 13 2\times 1+2\times 3+5=13 2×1+2×3+5=13
分别单独对正轴和负轴实行上述策略即可。
然后因为,我们最后选择是呆在最左边还是最右边取决于两边绝对值的大小
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5+100;
int a[maxn];
int n,k;
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
cin>>n>>k;
for (int i=1;i<=n;++i)cin>>a[i];
sort(a+1,a+1+n);
ll ans = 0;
for (int i=1;i<=n&&a[i]<0;i+=k)
ans += 2*abs(a[i]);
for (int i=n;i>0&&a[i]>0;i-=k)
ans += 2*a[i];
ans -= max(abs(a[1]), abs(a[n]));
cout<
给你个长为n的数组,你之可以进行 3 − c y c l e 3-cycle 3−cycle变换,问是否可以实现排序
3 − c y c l e 3-cycle 3−cycle的定义是:
选取 i , j , k i,j,k i,j,k互不相等,然后让 a [ i ] → a [ j ] → a [ k ] → a [ i ] a[i]\rightarrow a[j]\rightarrow a[k]\rightarrow a[i] a[i]→a[j]→a[k]→a[i]
拿到现有的数组之后a
我们得到一个排序后的数组b
按照b我们可以得知a数组中的每一个数 a i a_i ai应该到哪一个索引 j j j
因此,可以建成一张图
也就是,一个个环。
分奇偶环考虑
考虑奇环,对于长度为 1 , 3 1,3 1,3的奇环,显然可以排序成功
对于长度为 5 5 5的奇环,例如数组: 2 , 3 , 4 , 5 , 1 2,3,4,5,1 2,3,4,5,1
环为: 1 → 2 → 3 → 4 → 5 → 1 1\rightarrow 2\rightarrow 3\rightarrow 4\rightarrow 5\rightarrow 1 1→2→3→4→5→1
假设我们选取 i = 3 , j = 4 , k = 5 i=3,j=4,k=5 i=3,j=4,k=5
那么,数组变为: 2 , 3 , 1 , 4 , 5 2,3,1,4,5 2,3,1,4,5
只剩下一个长为 3 3 3的奇环。
也就是说,对于任意的奇环,我们都可以 − 2 , − 2 , … , − 2 -2,-2,\dots,-2 −2,−2,…,−2地使得他们变成长度只有 3 3 3的奇环,从而实现排序
偶环的情况下:
观察所给样例:
2 , 1 , 4 , 3 2,1,4,3 2,1,4,3
这里两个偶环的情况下是可以实现排序的
原因是,两个偶环可以一次 3 − c y c l e 3-cycle 3−cycle操作变成一个奇环
因此,如果有偶环则一定要使得偶环的数目是偶数
而如果数组a中有重复的元素的话,我们划分的偶数环的个数是不一样的
我们可以通过重复元素,来调节偶数环的个数,从而导致一定可以排序成功!
#include
using namespace std;
typedef long long ll;
const int maxn = 5e5+100;
int G[maxn];
int a[maxn];
int vis[maxn];
int n;
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
cin>>n;
for (int i=1;i<=n;++i)vis[i]=G[i]=0;
bool f = false;
for (int i=1;i<=n;++i)
{
cin>>a[i];
if (G[a[i]]!=0)f=true;
G[a[i]]=i;
}
if (n==1)
{
cout<<"YES\n";
continue;
}else if(n==2)
{
if (a[1]<=a[2])cout<<"YES\n";
else cout<<"NO\n";
continue;
}
if (f)
{
cout<<"YES\n";
continue;
}
sort(a+1,a+1+n);
int cnt = 0;
for (int i=1;i<=n;++i)if (!vis[i])
{
int cur = i;
int len = 0;
while (true)
{
vis[cur]=1;
++len;
cur = G[a[cur]];
if (vis[cur])break;
}
if (len%2==0)++cnt;
}
if (cnt&1)cout<<"NO\n";
else cout<<"YES\n";
}
}
给一颗n个节点的树,每个点的点权在 1 1 1到 n n n之间
有 q q q次查询,每次查询格式如下:
v , l , k v,l,k v,l,k
要求返回:
从点 v v v到根节点的最短路径上,出现次数大于 l l l次的点权中,按照出现此书排序的
第 k k k多的点权值,如果有并列情况则返回任意即可。
我们可以离线解决这个问题
先记录出每个点上的查询。
然后从根节点开始 d f s dfs dfs,在 d f s dfs dfs的过程中维护线段树,利用线段树实现查询
每次 d f s dfs dfs到一个新的节点时,我们线段树对这个点权出现次数加一
然后利用线段树查询这个点上所有的询问
之后回溯的过程时,我们再在线段树上删去这个点权
#include
using namespace std;
const int N=1e6+10;
setst[N],exi;
struct que{
int l,k,num;
};
vectorv[N];
int t,n,q,ans[N],val[N],tim[N];
struct edge{
int to,nex;
};
edge ed[N<<1];
int cnt,h[N];
void add(int st,int et){
cnt++;
ed[cnt].to=et;
ed[cnt].nex=h[st];
h[st]=cnt;
}
int sum[N<<2];
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void upd(int rt,int l,int r,int L,int R,int d)
{
if(L<=l && r<=R)
{
sum[rt]+=(r-l+1)*d;
return;
}
int mid=(l+r)>>1;
if(L<=mid) upd(rt<<1,l,mid,L,R,d);
if(R>mid) upd(rt<<1|1,mid+1,r,L,R,d);
pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if(L<=l && r<=R)
{
return sum[rt];
}
int mid=(l+r)>>1,res=0;
if(L<=mid) res += query(rt<<1,l,mid,L,R);
if(R>mid) res += query(rt<<1|1,mid+1,r,L,R);
return res;
}
int getval(int rt,int l,int r,int now){
if(l==r)return l;
int mid=(l+r)>>1;
if(sum[rt<<1]