首页 > 其他分享 >HDU 6964 I love counting

HDU 6964 I love counting

时间:2024-11-11 22:31:29浏览次数:1  
标签:HDU ch love cur int back counting id log

看到 \(\oplus\),肯定想到 trie。当我们一位可以是 \(1\) 但是变成 \(0\) 时,一个子树内的都合法。特殊的,最后走到的叶子也合法。

想法负一:我会莫队!时间复杂度 \(\mathcal{O}(n\sqrt{n}\log n)\),待更新。

想法零:我会树套树!待更新。

想法一:我会 HH 的项链!我们按照 \(r\) 离线,每一次查询变成了找到合法的上一次出现 \(\ge l\) 的个数。按照 trie 上的 dfn 序建成一个线段树(每个节点维护上一次出现的位置),因为 trie 两个不互为祖先的子树不相交,问题变成了:一个询问做多有 \(\log n\) 个区间,问区间内大于等于一个数的个数。可以二分+主席树做到 \(\mathcal{O}(n\log^3 n)\),或者主席树上二分做到 \(\mathcal{O}(n\log^2 n)\)。

这东西常数又大又难写,能不能再给力一点?

想法二:HH 的项链记录的贡献是最后一个出现的位置!那么我们一个数对 \((c,pos)\)(这个数,这个数出现的位置)在 \([L,R]\) 贡献到不仅要 \(c\) 本生合法,要 \(L\le pos\le R<nxt\),\(nxt\) 是下一个的位置。那么如果没有 trie 的限制(HH 的项链),就是一个普通的二维数点问题,数 \(L\le l\le R<r\) 的个数,右端点排序,相同先排询问来解决。其实有了 trie 的限制也是简单的。现在已经知道总共有 \(\mathcal{O}(n\log n)\) 个子树会有贡献,子树叶子数量之和是 \(\mathcal{O}(n\log n)\) 的(因为我们是 trie),那么我们可以离线下来,对于每一个子树算出会对哪些询问产生贡献,子树内做一个二维数点即可。这个是均摊 \(\mathcal{O}(n\log n)\) 的。

Code for 2
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

const int N = 1e5+5;

int n,q,cnt=1,c[N],nxt[N],ch[N*18][2],ans[N],L[N],R[N];
vector<pair<int,int> > g[N*18];
vector<int> as[N*18];

void ins(int x,int p1,int p2){
	int cur=1;
	g[1].push_back({p1,p2});
	for (int i=17; i>=0; i--){
		int f=(x>>i&1);
		if (!ch[cur][f]) ch[cur][f]=++cnt;
		cur=ch[cur][f];
		g[cur].push_back({p1,p2});
	}
}

void qy(int id,int a,int b){
	int cur=1;
	for (int i=17; i>=0; i--){
		int f1=(a>>i&1),f2=(b>>i&1);
		if (f2==0){
			cur=ch[cur][f1];
		}
		else{
			as[ch[cur][f1]].push_back(id);
			cur=ch[cur][f1^1];
		}
	}
	as[cur].push_back(id);
}

struct node {
	int l,r,id;
	bool operator < (const node &x) const {
		return r!=x.r?r>x.r:id>x.id;
	}
} a[N*18];

int top,bit[N];

void M(int p,int v){
	while (p<N){
		bit[p]+=v,p+=p&-p;
	}
}

int Q(int p){
	int res=0;
	while (p){
		res+=bit[p],p-=p&-p;
	}
	return res;
}

void sol(int id){
	top=0;
	for (auto u : g[id]) a[++top]={u.first,u.second,0};
	for (auto u : as[id]) a[++top]={L[u],R[u],u};
	sort(a+1,a+1+top);
	for (int i=1; i<=top; i++){
		if (!a[i].id) M(a[i].l,1);
		else ans[a[i].id]+=Q(a[i].r)-Q(a[i].l-1);
	}
	for (int i=1; i<=top; i++){
		if (!a[i].id) M(a[i].l,-1);
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n;
	for (int i=1; i<=n; i++){
		cin>>c[i];
		nxt[i]=n+1; 
	}
	for (int i=n; i; i--){
		ins(c[i],i,nxt[c[i]]);
		nxt[c[i]]=i;
	}
	cin>>q;
	for (int i=1; i<=q; i++){
		int a,b;
		cin>>L[i]>>R[i]>>a>>b;
		qy(i,a,b);
	}
	for (int i=1; i<=cnt; i++){
		sol(i);
	}
	for (int i=1; i<=q; i++){
		cout<<ans[i]<<"\n";
	}
	return 0;
}

标签:HDU,ch,love,cur,int,back,counting,id,log
From: https://www.cnblogs.com/SFlyer/p/18540707

相关文章

  • [极客大挑战 2019]LoveSQL
    打开是一个登录界面使用admin'or1#万能密码绕过密码登录再使用admin'orderby3#找回显的列数,结果为3,再使用a'unionselect1,2,3#找回显的列,结果为2,3后面就是常规的union注入流程#找数据库和表名a'unionselect1,database(),group_concat(table_name)frominfor......
  • [AGC005D] ~K Perm Counting
    题意求对于所有的\(i\)满足\(|P_i-i|\neqk\),的排列数量,对\(924844033\)取模。\(2\len\le2\times10^3,1\lek\len-1\)。Sol考虑转成\(n\timesn\)的网格图,那么就是所有\((i,i+k)\)以及\((i,i-k)\)的格子涂黑不能用。题意转化为在网格图里......
  • 并查集 How many tables(hdu 1213) How many answers are wrong(hdu 3038)
    目录前言并查集  并查集的初始化  并查集的合并  并查集合并的优化,路径压缩Howmanytables(hdu1213)  问题描述  输入  输出问题分析代码带权并查集Howmanyanswersarewrong(hdu3038)  问题描述  输入  输出问题分析代码......
  • [极客大挑战 2019]LoveSQL 1
    [极客大挑战2019]LoveSQL1代码审计,发现表单方式为get提交到check.php万能密码admin'or1=1#登录成功,这边我以为密码就是flag,结果并不是,结合题目信息,猜想这应该是根据账号密码的注入尝试闭合?username=admin'and1=1%23&password=d3c9cf30a12d1f13d4f778859fb16f73正......
  • 题解:HDU5628 Clarke and math
    数学题可爱捏~HintAnalysis注意到形式很好看,猜测是某种神奇迭代。考虑特殊情况\(k=1\),于是有:\(g(i)=\sum_{i_1\midi}f(i_1)=(f*1)(i)\)$即\(g=f*1\)。于是猜测\(g=f*1^k\),这里的幂运算表示多次Dirichlet卷积。简单证明一下,采用数学归纳法:基本情况\(k=1\),已经证过,......
  • [极客大挑战 2019]LoveSQL
    题目链接:https://buuoj.cn/challenges#[极客大挑战2019]LoveSQL。打开环境后,如下所示。尝试SQL注入(万能密码)。Payload:admin'+or+1%3d1%3b%23。(笔者通过简单粗暴的尝试:①没有使用单引号;②使用单引号;③使用双引号,来确定后端拼接的SQL语句中的password参数系使用单引号......
  • 数组排序简介-计数排序(Counting Sort)
    基本思想        通过统计数组中每个元素在数组中出现的次数,根据这些统计信息将数组元素有序的放置到正确位置,从而达到排序的目的。算法步骤计算排序范围:遍历数组,找出待排序序列中最大值元素 nums_max和最小值元素 nums_min,计算出排序范围为 nums_max−nums_min......
  • [HDU 2509] Be the Winner (博弈、分裂游戏)
    本质上是一个Anti-NimGame。考虑如何计算SG函数。如果当前有堆\(x\)个石子,我取出任意个后,一定会把当前堆分为左右两堆,我们可以枚举左右两堆的大小\(l,r\),保证\(0\lel+r<x\),则有\[SG(x)=\mathrm{mex}(SG(l)\oplusSG(r))\]#include<bits/stdc++.h>usingnames......
  • P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III
    Sol蒲公英题意基本相同,但是注意到空间限制62.5MB,显然不能用蒲公英的做法。考虑先把整块的答案算出来,然后把小块的部分补上去,显然大块可以预处理,小块可以直接暴力查询是否越界。代码很简单。Code#include<iostream>#include<iomanip>#include<cstdio>#include<vector>......
  • GCD Counting
    算法\(\mathcal{O}(n\logn)\)算法,\(95pts\)观察题目,发现题目要求我们求\(\gcd\)不等于\(1\)的一条最长链考虑将每个数分解质因数对于每一个\(1\simk\)中的质数,将所有含有这个质因子的数加入一颗虚树,求最长链即可,经过尝试发现\(k=700\)时即可通过可以......