[bzoj4994][Usaco2017 Feb]Why Did the Cow Cross the Road III_树状数组

Why Did the Cow Cross the Road III bzoj-4994 Usaco-2017 Feb

题目大意:给定一个长度为$2n$的序列,$1$~$n$个出现过两次,$i$第一次出现的位置记为$a_i$,第二次记为$b_i$,求满足$a_i<a_j<b_i<b_j$的个数。

注释:$1\le n\le 10^5$。


想法

这个题有一个非常不一样的地方。

我记得我之前做过的长成这样的题大概都是第一个位置+1,第二个位置-1即可。

这个题我们只能对第一个位置进行操作。

如果第一次碰见了这个数,就将当前位置+1

如果是第二次碰见了这个数,我们先更新答案,然后把这个数第一个出现的位置-1即可。

Code

#include <bits/stdc++.h>
#define N 100010 
using namespace std; typedef long long ll;
int tr[N<<2],vis[N],a[N<<1],n;
inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
inline int lowbit(int x) {return x&(-x);}
void update(int x,int val) {for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=val;}
ll query(int x) {ll ans=0; for(int i=x;i;i-=lowbit(i)) ans+=tr[i]; return ans;}
int main()
{
	ll ans=0; n=rd()*2; for(int i=1;i<=n;i++) a[i]=rd(); for(int i=1;i<=n;i++)
	if(!vis[a[i]]) update(i,1),vis[a[i]]=i;
	else ans+=query(i)-query(vis[a[i]]),update(vis[a[i]],-1);
	cout << ans << endl ;
	return 0;
}

小结:树状数组是非常有用的啊,要熟练掌握才是。

全部评论

相关推荐

三题看不懂四题不明白二题无法AC&nbsp;T=int(input())&nbsp;for&nbsp;_&nbsp;in&nbsp;range(T):&nbsp;n=int(input())&nbsp;s=input().split()&nbsp;k,mx=1,1&nbsp;for&nbsp;i&nbsp;in&nbsp;range(len(s)-1):&nbsp;if&nbsp;len(s[i])&lt;len(s[i+1]):&nbsp;k+=1&nbsp;elif&nbsp;len(s[i])==len(s[i+1]):&nbsp;if&nbsp;s[i]&lt;=s[i+1]:&nbsp;k+=1&nbsp;...
恭喜臭臭猴子:第二题用栈就行。合法的括号直接出栈了,剩下的是不合法的,肯定都得一个一个走。出入栈的过程中得记下进栈的括号的下标。最后栈里剩下的括号如果相邻两个的下标不连续,说明它们中间有一个合法的括号序列被出栈,结果加一
投递拼多多集团-PDD等公司10个岗位 > 拼多多求职进展汇总 笔试
点赞 评论 收藏
分享
03-27 17:33
门头沟学院 Java
代码飞升:同学院本,你要注意hr当天有没有回复过,早上投,还要打招呼要推销自己,不要一个劲投
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务