【nodgd电路图B】线段树维护函数变换

这种题现在只见过两次,每次都觉得还是很神奇的,,,主要还是我太弱了orz orz orz 网上找不到链接和文字题面(NK的同学可以做到哦),简述题意:现在有横着一排n个电阻(n<=2.5*10^5),现在有m个操作(m<=2.5*10^5),1查询区间最小,2查询区间最大,3给区间每一个电阻串联上一个电阻值为R电阻,4给区间的每一个电阻并联上一个电阻值为R电阻。 物理题orz orz orz,做出来感谢hdhd和OBlack大佬的提示与帮助。我们可以将其每次变换转换为一个函数,(Ax + B / Cx + D) ,然后如果先执行某个函数再执行某个函数,就是将第一个函数代入第二个函数中,显然又会得到一个同阶的函数(因为这是一个线性的函数),这就是一次函数变换。 显然,对于一个电阻串联上一个新的电阻(阻值为R)的函数应该为(A=1,B=R,C=0,D=1),同时对于并联函数应该是(A=R,B=0,C=1,D=R)这样就可以完美表达出变换了。 之后就是一个区间极大值和区间极小值,区间覆盖函数,lazy putdowm函数下去的线段树问题了。有个毒点,函数A,B,C,D可能在多次变换后会变得极大导致精度有鬼,所以我们完全可以将A调整成1,其他同时/A,将他们的数据范围拉回来。 对于这些函数变换题的函数形式不是卡死的,就比如这次就是分式,所以应该及时调整思维。 code:
#include<iostream> 
#include<cstdio> 
#include<cmath> 
#include<algorithm>

using namespace std; 
const int maxn = 500005; 
int ls[maxn],rs[maxn],tot,rt; 
double maxr[maxn],minr[maxn]; 
bool lazb[maxn]; 
struct node { 
    double a,b,c,d; 
}ttmp,lazy[maxn]; 
inline void gaoji(int &p) {
	if(maxr[p]<minr[p]) swap(maxr[p],minr[p]);
}
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
inline int R()
{
	char t=GC;
	int x=0;
	while(!isdigit(t)) t=GC;
	while(isdigit(t)) x=x*10+t-48,t=GC;
	return x;
}
void bianhuan(node &x,node &aa,node &bb) { 
    ttmp.a = aa.a*bb.a + aa.c*bb.b; 
    ttmp.b = aa.b*bb.a + aa.d*bb.b; 
    ttmp.c = aa.a*bb.c + aa.c*bb.d; 
    ttmp.d = aa.b*bb.c + aa.d*bb.d; 
    
	ttmp.b /= ttmp.a;
    ttmp.c /= ttmp.a;
    ttmp.d /= ttmp.a;
    ttmp.a = 1.0;
	x = ttmp; 
} 
int n; 
void chuanlian(node &x,int rr) { 
    x.a=1; x.b=1.0*rr; x.c=0; x.d=1.0; 
} 
void binglian(node &x,int rr) { 
    x.a=1.0*rr; x.b=0; x.c=1; x.d=1.0*rr; 
} 
double dairu(double x,node &hs) { 
    return  ( ( hs.a * x + hs.b) / (hs.c * x + hs.d) ); 
} 
void putdowm(int x) { 
    if(!lazb[x]||(!ls[x])) return; 
     
    maxr[ls[x]] = dairu(maxr[ls[x]],lazy[x]); 
    minr[ls[x]] = dairu(minr[ls[x]],lazy[x]); 
    gaoji(ls[x]);
	if(!lazb[ls[x]]) lazb[ls[x]]=1,lazy[ls[x]]=lazy[x]; 
    else bianhuan(lazy[ls[x]],lazy[ls[x]],lazy[x]); 
     
    maxr[rs[x]] = dairu(maxr[rs[x]],lazy[x]); 
    minr[rs[x]] = dairu(minr[rs[x]],lazy[x]); 
    gaoji(rs[x]);
	if(!lazb[rs[x]]) lazb[rs[x]]=1,lazy[rs[x]]=lazy[x]; 
    else bianhuan(lazy[rs[x]],lazy[rs[x]],lazy[x]); 
    
    lazb[x] = 0; 
} 
inline void update(int p) { 
    maxr[p] = max(maxr[ls[p]],maxr[rs[p]]); 
    minr[p] = min(minr[ls[p]],minr[rs[p]]); 
} 
void maketree(int &p,int l,int r) { 
    p = ++tot; 
    if(l==r) { 
        int x; x=R();
        minr[p] = maxr[p] = (double)x; return;
    } 
    int mid = (l+r)>>1; 
    maketree(ls[p],l,mid); 
    maketree(rs[p],mid+1,r); 
    update(p); 
} 
double querymax(int p,int l,int r,int x,int y) {
	if(x<=l&&r<=y) return maxr[p];
	putdowm(p);
	int mid = (l+r)>>1;
	if(y<=mid) return querymax(ls[p],l,mid,x,y);
	else if(x>mid) return querymax(rs[p],mid+1,r,x,y);
	else return max(querymax(ls[p],l,mid,x,y),querymax(rs[p],mid+1,r,x,y));
}
double querymin(int p,int l,int r,int x,int y) {
	if(x<=l&&r<=y) return minr[p];
	putdowm(p);
	int mid = (l+r)>>1;
	if(y<=mid) return querymin(ls[p],l,mid,x,y);
	else if(x>mid) return querymin(rs[p],mid+1,r,x,y);
	else return min(querymin(ls[p],l,mid,x,y),querymin(rs[p],mid+1,r,x,y));
}
void add(int p,int l,int r,int x,int y,node &d) {
	if(x<=l&&r<=y) {
		maxr[p] = dairu(maxr[p],d); minr[p] = dairu(minr[p],d);
		if(!lazb[p])  { lazy[p] = d;lazb[p]=1; } 
		else bianhuan(lazy[p],lazy[p],d);
		gaoji(p);
;		return;
	}
	int mid = (l+r)>>1;
	putdowm(p);
	if(y<=mid) add(ls[p],l,mid,x,y,d);
	else if(x>mid) add(rs[p],mid+1,r,x,y,d);
	else add(ls[p],l,mid,x,y,d),add(rs[p],mid+1,r,x,y,d);
	update(p);
}
int main() { 
    n=R();
    maketree(rt,1,n); 
    int m; m=R();
    for(int i=1;i<=m;i++) {
    	int opt,l,r,orz; opt=R();l=R();r=R();
    	switch(opt) {
    		case 1:{
    			printf("%.14lf\n",querymax(rt,1,n,l,r));
				break;
			}
			case 2:{
				printf("%.14lf\n",querymin(rt,1,n,l,r));
				break;
			}
			case 3:{
				orz=R();
				node tmp; chuanlian(tmp,orz);
				add(1,1,n,l,r,tmp);
				break;
			}
			case 4:{
				orz=R();
				node tmp; binglian(tmp,orz);
				add(1,1,n,l,r,tmp);
				break;
			}
		}
	}
}
 
posted @ 2018-09-20 23:09  Newuser233  阅读(11)  评论(0)    收藏  举报