Wannafly挑战赛16
E(pbds)
题意:
1<=m,n<=5e5
分析:
首先指向关系形成了一个基环外向树森林
实际上我们可以完全不用真正的去移动每个球,而只需要在计数的时候考虑考虑就行了
对于树上的情况,我们假设在时间为now的时候在距离根为dis的点上放了个球,我们记录下now+dis
对于询问树上的情况,即查找在时间为i的时候有多少个球会到达x点,那么我们只需要考虑以x为根的子树里(now+dis==i+d[x])的个数即可,很显然这可以用dfs序+数据结构来搞
这个数据结构需要支持单点修改、询问区间内某一数字出现了多少次
树状数组+主席树?
我们换个角度,因为数字都不大,我们不妨对于每个数字都开一个set,查找就是在对应数字里的set里查找[l,r]中的数字有多少个,这个用pbds里的set就行了
还有一个case,如果询问在环上咋办?
我们可以记录每个球来到环上的时间,对于每个环直接用带模数组维护即可
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#define mp make_pair
using namespace std;
using namespace __gnu_pbds;
const int inf=;
typedef tree<pair<int,int>,null_type,less<pair<int,int> >,rb_tree_tag,tree_order_statistics_node_update> rbtree;
const int maxn=5e5;
int f[maxn+],fa[maxn+],c[maxn+],len[maxn+];
int L[maxn+],R[maxn+],dep[maxn+],root[maxn+],id[maxn+];
int n,m,ans,dfn,color;
vector<int> g[maxn+];
rbtree rbt[*maxn+];
multiset<pair<int,int> > s;
map<int,int> a[maxn+];
int find(int k)
{
if(f[k]==k) return k;
return f[k]=find(f[k]);
}
void addedge(int u,int v)
{
g[u].push_back(v);
}
void dfs(int k)
{
L[k]=++dfn;
for(auto u:g[k])
{
if(c[u]) continue;
dep[u]=dep[k]+;
root[u]=root[k];
dfs(u);
}
R[k]=dfn;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i) f[i]=i;
for(int i=;i<=n;++i) scanf("%d",&fa[i]),addedge(fa[i],i);
for(int i=;i<=n;++i)
{
int u=find(i),v=find(fa[i]);
if(u!=v)
{
f[u]=v;
continue;
}
u=fa[i];
++color;
int tmp=;
while(true)
{
++len[color];
c[u]=color;
id[u]=tmp++;
u=fa[u];
if(u==fa[i]) break;
}
}
for(int i=;i<=n;++i)
if(c[i]) root[i]=i,dfs(i);
scanf("%d",&m);
for(int i=;i<=m;++i)
{
int x;
scanf("%d",&x);
x^=ans;
if(c[x])
{
s.insert(mp(i,x));
while(!s.empty())
{
pair<int,int> u=*s.begin();
if(u.first>i) break;
int color=c[u.second];
++a[color][(u.first-id[u.second]+len[color])%len[color]];
s.erase(s.begin());
}
int color=c[x];
ans=a[color][(i-id[x]+len[color])%len[color]];
printf("%d\n",ans);
}
else
{
rbt[i+dep[x]].insert(mp(L[x],i));
ans=rbt[i+dep[x]].order_of_key(mp(R[x],inf))-rbt[i+dep[x]].order_of_key(mp(L[x],-inf));
printf("%d\n",ans);
s.insert(mp(i+dep[x],root[x]));
}
}
return ;
}
F(数据结构)
题意:
分析:
首先不考虑修改,对于一个给定的数组a,我们如何快速求出需要执行多少次操作才能把它全部变成0?
我们可以发现以下的性质:
1、有些位置对最终答案满贡献,其它位置对最终答案0贡献
2、极大值对最终答案是满贡献的
3、我们从初始的所有极大值开始每次隔1个数,直到遇到边界或者极小值,那么数到的数都会在过程中成为极大值
4、若一个极小值对答案有贡献,那么它到两边的极大值的距离都为偶数
于是我们就可以O(n)解决了
但是现在有修改操作,我们来考虑如何在之前信息的基础上维护一些东西
求答案的本质是找到那些极大值极小值,然后从极大值开始间隔1个数,我们可以用两个树状数组来维护奇数位/偶数位上的前缀和
然后我们用一个set去存下所有的极大值、极小值
对于一个修改(x,y)
我们找到一个set里的极小区间[l,r],使得l和r的极大极小性质一定不会被破坏
然后把这段区间对答案的贡献减掉
然后修改a[x]->y
再把这段区间对答案的贡献加上去
时间复杂度O(nlogn)
#include<bits/stdc++.h>
using namespace std;
typedef set<int>::iterator iter;
typedef long long ll;
const int maxn=1e5;
ll c[][maxn+];
ll a[maxn+];
int n;
ll ans=;
set<int> s;
int lowbit(int x)
{
return x&(-x);
}
void add(ll *c,int k,ll x)
{
for(;k<=n/+;k+=lowbit(k)) c[k]+=x;
}
void add(int k,ll x)
{
if(k&) add(c[],(k+)>>,x);else add(c[],(k+)>>,x);
}
ll query(ll *c,int k)
{
ll ans=;
for(;k;k-=lowbit(k)) ans+=c[k];
return ans;
}
ll query(ll *c,int l,int r)
{
if(l>r) return ;
return query(c,r)-query(c,l-);
}
int type(int id)
{
if(a[id-]<a[id]&&a[id]>=a[id+]) return ;
if(a[id-]>=a[id]&&a[id]<a[id+]) return -;
return ;
}
ll cal(int l,int r)
{
if(r-l<) return ;
if(a[l]<a[r])
{
int R=(r+)/-;
int L;
if((l&)==(r&)) L=(l+)/+;else L=(l+)/;
return query(c[r&],L,R);
}
else
{
int L=(l+)/+;
int R;
if((l&)==(r&)) R=(r+)/-;else R=r/;
return query(c[l&],L,R);
}
}
ll cal(iter l,iter r)
{
ll ans=;
for(iter i=l;i!=r;++i)
{
iter tmp=i;
++tmp;
ans+=cal(*i,*tmp);
}
++r;
for(iter i=l;i!=r;++i)
if(type(*i)==) ans+=a[*i];
else
if(type(*i)==-)
{
iter tmp1=i,tmp2=i;
--tmp1,++tmp2;
if((*tmp2-*i)%==&&(*i-*tmp1)%==) ans+=a[*i];
}
else
{
iter tmp=i;
if(*i==) ++tmp;else --tmp;
if((*tmp-*i)%==) ans+=a[*i];
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i) scanf("%lld",&a[i]),add(i,a[i]);
s.insert(),s.insert(n);
for(int i=;i<n;++i)
if(type(i)!=) s.insert(i);
iter tmp=s.end();
ans=cal(s.begin(),--tmp);
int q;
scanf("%d",&q);
for(int i=;i<=q;++i)
{
int x;ll y;
scanf("%d%lld",&x,&y);
int l=x-,r=x+;
if(r>n-) r=n-;
if(l<) l=;
iter L=s.lower_bound(l);
--L;
iter R=s.upper_bound(r);
ans-=cal(L,R);
int left=*L,right=*R;
add(x,y-a[x]);
a[x]=y;
if(type(x)!=) s.insert(x);
else if(s.count(x)&&x>=&&x<=n-) s.erase(x);
if(x+<n)
if(type(x+)==&&s.count(x+)) s.erase(x+);
else if(type(x+)!=) s.insert(x+);
if(x->)
if(type(x-)==&&s.count(x-)) s.erase(x-);
else if(type(x-)!=) s.insert(x-);
L=s.lower_bound(left);
R=s.lower_bound(right);
ans+=cal(L,R);
printf("%lld\n",ans);
}
return ;
}
Wannafly挑战赛16的更多相关文章
- Wannafly 挑战赛16 A 取石子
题目描述 给出四堆石子,石子数分别为a,b,c,d.规定每次只能从堆顶取走石子,问取走所有石子的方案数. 输入描述: 在一行内读入四个由空格分隔的整数a,b,c,d, 输入均为不超过500的正整数 输 ...
- Wannafly挑战赛16 #E 弹球弹弹弹 splay+基环树+各种思维
链接:https://ac.nowcoder.com/acm/problem/16033来源:牛客网 有n个位置,标号为1到n的整数,m次操作,第i次操作放置一个弹球在b[i] xor c[i-1]处 ...
- Wannafly 挑战赛 19 参考题解
这一次的 Wannafly 挑战赛题目是我出的,除了第一题,剩余的题目好像对大部分算法竞赛者来说好像都不是特别友好,但是个人感觉题目质量还是过得去的,下面是题目链接以及题解. [题目链接] Wanna ...
- Wannafly挑战赛25游记
Wannafly挑战赛25游记 A - 因子 题目大意: 令\(x=n!(n\le10^{12})\),给定一大于\(1\)的正整数\(p(p\le10000)\)求一个\(k\)使得\(p^k|x\ ...
- Wannafly挑战赛27
Wannafly挑战赛27 我打的第一场$Wannafly$是第25场,$T2$竟然出了一个几何题?而且还把我好不容易升上绿的$Rating$又降回了蓝名...之后再不敢打$Wannafly$了. 由 ...
- Wannafly挑战赛21A
题目链接 Wannafly挑战赛21A 题解 代码 #include <cstdio> #include <cmath> #define MAX 1000005 #define ...
- Wannafly挑战赛24游记
Wannafly挑战赛24游记 A - 石子游戏 题目大意: A和B两人玩游戏,总共有\(n(n\le10^4)\)堆石子,轮流进行一些操作,不能进行下去的人则输掉这局游戏.操作包含以下两种: 把石子 ...
- Wannafly挑战赛25C 期望操作数
Wannafly挑战赛25C 期望操作数 简单题啦 \(f[i]=\frac{\sum_{j<=i}f[j]}{i}+1\) \(f[i]=\frac{f[i]}{i}+\frac{\sum_{ ...
- Wannafly挑战赛18B 随机数
Wannafly挑战赛18B 随机数 设\(f_i\)表示生成\(i\)个数有奇数个1的概率. 那么显而易见的递推式:\(f_i=p(1-f_{i-1})+(1-p)f_{i-1}=(1-2p)f_{ ...
随机推荐
- loc与iloc函数的使用
Pandas中loc和iloc函数用法详解(源码+实例) https://blog.csdn.net/w_weiying/article/details/81411257 Pandas中loc,il ...
- 【HIHOCODER 1420】 Bigint Multiplication
描述 Given 2 nonnegative integers a and b, calculate a × b. 输入 One line with 2 integers a and b separa ...
- SpringMVC之Controller简单使用
//环境 spring-4.3.18/JDK1.8/开发工具/IntelliJ IDEA 2018.2.5 x64 //工程结构图 //web.xml <?xml version="1 ...
- debian使用ibus
$ sudo apt-get install ibus ibus-pinyin 点击右上角的键盘图标,设置拼音输入法
- Mysql之查看数据库版本
Mysql版本: 登入数据库的时候: select @@version; select version(); mysql> select @@version; +-----------+ | @ ...
- ant 入门级详解
ant 入门级详解 [转载的地址(也是转载,未找到原文地址)]https://www.cnblogs.com/jsfx/p/6233645.html 1,什么是antant是构建工具2,什么是构建 ...
- Flask_WTForms源码流程(糙版)
from flask import Flask, render_template, request, redirect # Form# _fields# validate# validata_name ...
- python补漏----isinstance 和 issubclass
一.isinstance Python 中的isinstance函数 isinstance是Python中的一个内建函数 语法: isinstance(object, classinfo) 如果参数o ...
- .Net程序员自学dump分析教程
文章:.Net程序员自学dump分析教程 可以分析内存状态.
- tomcat(不仅仅是tomcat)通过熵池解决在linux启动应用慢
tomcat启动过程中报错 -Jul- ::] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web applica ...