#RMQ,ST表#hdu 6356 Glad You Came

题目

经过一波玄学的操作得到左端点 l l l,右端点 r r r A [ l , r ] = max ⁡ ( [ l , r ] , v a l u e ) A[l,r]=\max([l,r],value) A[l,r]=max([l,r],value)
多组数据,求 x o r i = 1 n A [ i ] ∗ i xor_{i=1}^nA[i]*i xori=1nA[i]i


分析

这道题首先先放玄学操作

int answer(){
	x^=(x<<11); x^=(x>>4); x^=(x<<5); x^=(x>>14);
	uit w=x^y^z; x=y; y=z; z=w; return z;
}
f1=answer(); f2=answer(); v=answer()%1073741824;
l=min(f1%n+1,f2%n+1); r=max(f1%n+1,f2%n+1);

不多说玄学操作QAQ
然后其它呢,怎样把答案从每个区间缩到单点,线段树?理论上查询 O ( l o g n ) O(logn) O(logn)会超时,然并卵,所以就用一种神奇的逆ST表
f [ i ] [ j − 1 ] = m a x { f [ i ] [ j − 1 ] , f [ i ] [ j ] } f[i][j-1]=max\{f[i][j-1],f[i][j]\} f[i][j1]=max{f[i][j1],f[i][j]}
f [ i + 2 j − 1 ] [ j − 1 ] = m a x { f [ i + 2 j − 1 ] [ j − 1 ] , f [ i ] [ j ] } f[i+2^{j-1}][j-1]=max\{f[i+2^{j-1}][j-1],f[i][j]\} f[i+2j1][j1]=max{f[i+2j1][j1],f[i][j]}


代码

#include <cstdio>
#include <algorithm>
typedef unsigned uit;
uit f[100001][17],ln[100001],t,n,m,x,y,z;
uit in(){
	uit ans=0; char c=getchar();
	while (c<48||c>57) c=getchar();
	while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
	return ans;
}
void print(long long ans){if (ans>9) print(ans/10); putchar(ans%10+48);}
uit answer(){
	x^=(x<<11); x^=(x>>4); x^=(x<<5); x^=(x>>14);
	uit w=x^y^z; x=y; y=z; z=w; return z;
}
int main(){
	t=in();
	for (register uit i=2;i<=100000;i++) ln[i]=ln[i>>1]+1;
	while (t--){
		uit n,m,l,r,f1,f2,v,k; long long ans=0ll;
		n=in(); m=in(); x=in(); y=in(); z=in();
		while (m--){
			f1=answer(); f2=answer(); v=answer()%1073741824;
			l=std::min(f1%n+1,f2%n+1); r=std::max(f1%n+1,f2%n+1);
			k=ln[r-l+1]; f[l][k]=std::max(f[l][k],v); 
			f[r-(1<<k)+1][k]=std::max(f[r-(1<<k)+1][k],v);//首先得到两个区间增加
		}
		for (register uit j=ln[n];j>=1;j--)//RMQ
		for (register uit i=1;i<=n;i++){
			f[i][j-1]=std::max(f[i][j-1],f[i][j]);
			if (i+(1<<j-1)<=n) f[i+(1<<j-1)][j-1]=std::max(f[i+(1<<j-1)][j-1],f[i][j]);
			f[i][j]=0;
		}
		for (register long long i=1;i<=n;i++) ans^=f[i][0]*i,f[i][0]=0;//求答案
		if (ans) print(ans); else putchar('0'); putchar('\n');
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值