强题!dft!
来源:互联网 发布:管家婆软件多少钱 编辑:程序博客网 时间:2024/05/17 22:58
膜拜!dft!
题目来源
不知道是什么地方的集训题,总之很强就对了.
题目描述
题解
题目描述有点问题,y序列少写了个y0.
题意其实是这样的:
每次把[l,r]的序列取出来,进行dft变换,然后再放回原序列.
取出来进行变换是指,重新编号,并且变换只与[l,r]的序列有关,与原序列无关。
那么怎么做呢?先化简式子?理论上应该要化简式子,但是我的数学水平不足以解决这样的式子,那怎么办?先写个
于是我们可以发现一些规律:
对1,2,3,4进行两次变换之后变成了1,4,3,2;数值没有变,只有位置变化了;
对1,2,3,4,5,6进行两次变换变成了1,6,5,4,3,2.这下发现规律了!L位置的数不变,[L+1,R]的数反序;
那么询问的答案怎么算?根据打表结果,我们发现,这个变换一次之后的模长平方和等于变换之前的模长平方和。
这些结论我真的不会证明,也没有看到什么有用的题解,如果有大佬会证明的,可以在评论区教育我。
于是写个暴力就有50分了,如果用平衡树维护的话可以拿到100分。
Code
贴一份代码:
#include<cstdio>#include<algorithm>using namespace std;#define LL long long#define MAXN 105000int st[MAXN],top;struct node{ int ch[MAXN][2],fa[MAXN],rev[MAXN],tot,root,size[MAXN]; LL val[MAXN],sum[MAXN]; void cal(int p) { sum[p]=val[p]+sum[ch[p][0]]+sum[ch[p][1]]; size[p]=size[ch[p][0]]+size[ch[p][1]]+1; return ; } void zg(int x,int d) { int y=fa[x],z=fa[y]; if(ch[z][0]==y) { ch[z][0]=x; } else { ch[z][1]=x; } fa[x]=z; ch[y][d]=ch[x][!d]; fa[ch[y][d]]=y; ch[x][!d]=y; fa[y]=x; cal(y); cal(x); if(!fa[x]) { root=x; } return ; } void Rev(int p) { swap(ch[p][0],ch[p][1]); rev[p]^=1; return ; } void push(int p) { if(rev[p]) { if(ch[p][0]) { Rev(ch[p][0]); } if(ch[p][1]) { Rev(ch[p][1]); } rev[p]^=1; } return ; } void splay(int x,int to=0) { if(x==to) { return ; } int y,z; st[++top]=x; for(int i=x;fa[i]!=to;i=fa[i]) { st[++top]=fa[i]; } for(;top;--top) { push(st[top]); } while(fa[x]!=to) { y=fa[x]; z=fa[y]; if(z!=to) { if(ch[z][0]==y^ch[y][0]==x) { zg(x,ch[fa[x]][1]==x); } else { zg(y,ch[fa[y]][1]==y); } } zg(x,ch[fa[x]][1]==x); } return ; } void ins(LL v) { if(!root) { root=1; ++tot; sum[tot]=val[tot]=v; size[tot]=1; return ; } int p=root; while(ch[p][1]) { p=ch[p][1]; } size[++tot]=1; ch[p][1]=tot; sum[tot]=val[tot]=v; fa[tot]=p; splay(p); return ; } int kth(int k) { int p=root; while(p) { push(p); if(k==size[ch[p][0]]+1) { break; } else if(k<=size[ch[p][0]]) { p=ch[p][0]; } else if(k>size[ch[p][0]]+1) //因为没写这两个else,我调了3个小时!简直闯了鬼了! { k-=size[ch[p][0]]+1; p=ch[p][1]; } } return p; } void print() { for(int i=2;i<tot;i++) { printf("%d ",val[kth(i)]); } putchar('\n'); return ; }}T;int n,q,l,r;void _r(int& x,bool f=0){ char c=getchar(); while(c<'0'||c>'9') { f|=(c=='-'); c=getchar(); } for(x=0;c>='0'&&c<='9';c=getchar()) { x=(x<<1)+(x<<3)+c-'0'; } x=f?-x:x; return ;}int o[30],oo;void _w(LL x){ if(x==0ll) { putchar('0'); return ; } for(oo=0;x;x/=10ll) { o[++oo]=x%10ll; } for(;oo;--oo) { putchar('0'+o[oo]); } return ;}int main(){ //freopen("dft.in","r",stdin); //freopen("dft.out","w",stdout); _r(n); T.ins(0); for(int i=1,x;i<=n;i++) { _r(x); T.ins(1ll*x*x); } T.ins(0); _r(q); for(int i=1,a,b,c;i<=q;i++) { _r(l); _r(r); a=T.kth(l+1); T.splay(a); b=T.kth(r+2); T.splay(b,a); _w(T.sum[T.ch[b][0]]+T.val[a]); putchar('\n'); T.Rev(T.ch[b][0]); } return 0;}
阅读全文
0 0
- 强题!dft!
- dft
- DFT
- 什么是DFT,DFT是什么意思
- [DFT] Spyglass DFT
- FFT & DFT
- opencv - DFT
- 二维DFT
- DFT/DTFT
- opencv dft
- opencv DFT
- opencv dft
- 强
- 强!
- 强!
- DFT的AS2实现
- Some Link for DFT
- DFT(离散傅里叶变换)
- linux centos下 手动编译安装memcache 扩展
- NDK程序开发流程
- 【项目记录】山东大学场馆管理系统之——器材管理
- Python图像处理库(1)
- 【项目记录】山东大学场馆管理系统之——财务管理
- 强题!dft!
- 铺砖问题(状态压缩DP)
- python:模拟内置函数map的实现
- 对比线程安全和可重入函数
- Python图像处理库(2)
- 搜索总结
- 淘淘商城系列——全局异常处理
- 每天学一点Swift----面向对象下(五)
- Java swing 实现angrybird