BZOJ3323: [Scoi2013]多项式的运算

很水的一道Splay维护题

好吧我其实被卡的很惨。。。

常数大的要死

注意一下放标的顺序与时机这样可以大大减小常数

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
char c;
#define ll long long
inline void read(ll &a)
{
	a=0;do c=getchar();while(c<'0'||c>'9');
	while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
const
   ll mod=20130426;
struct Node
{
  Node *lc,*rc,*f;
  ll DeBug;
  ll add_delta,k_delta;
  ll ax_delta;
  ll k,ax;
inline bool l(){return f->lc==this;}
inline bool flag(){return add_delta||k_delta!=1||ax_delta;}	
inline friend Node operator +=(Node &a,Node b)
  {
  	a.k+=b.k;
  	return a;
  } 
}Tree[100002];
Node *root,*empty;

Node *build(ll l,ll r)
{
	if(r<l)return empty;
	Node *tp=&Tree[(l+r)>>1];
	tp->lc=build(l,((l+r)>>1)-1),tp->lc->f=tp,
	tp->rc=build(((l+r)>>1)+1,r),tp->rc->f=tp;
	return tp;
}

inline void begin()
{
	empty=new Node;
	empty->lc=empty;
	empty->rc=empty;
	for(ll i=0;i<=100001;i++)
	   Tree[i].ax=Tree[i].DeBug=i,Tree[i].k=0,Tree[i].add_delta=Tree[i].ax_delta=0,Tree[i].k_delta=1;
    root=build(0,100001);
    root->f=root;
    Tree[100001].ax=1ll<<62;
}
int ttp;
inline void Mod(Node *a)
{
	if(a==empty)return;
	ttp+=3;
	a->k%=mod;a->add_delta%=mod;a->k_delta%=mod;
}
void pushdown(Node *a)
{
    a->lc->add_delta=a->lc->add_delta*a->k_delta+a->add_delta;
    a->rc->add_delta=a->rc->add_delta*a->k_delta+a->add_delta;
    a->lc->k_delta=a->lc->k_delta*a->k_delta;
	a->rc->k_delta=a->rc->k_delta*a->k_delta;
	a->k=a->k*a->k_delta+a->add_delta;
	a->lc->ax_delta+=a->ax_delta;
	a->rc->ax_delta+=a->ax_delta;
	a->ax+=a->ax_delta;
	a->ax_delta=0;
	a->k_delta=1;
	a->add_delta=0;
	Mod(a->lc),Mod(a->rc),Mod(a);
}
inline void Lc(Node *a)
{
	Node *f;
	if(a->f==root)
        f=a,root=a;
	 else
	    if(a->f->l())
		  a->f->f->lc=a,f=a->f->f;
	else a->f->f->rc=a,f=a->f->f;
	a->rc->f=a->f;
	a->f->lc=a->rc;
	a->f->f=a;
	a->rc=a->f;
	a->f=f;
}
inline void Rc(Node *a)
{
	Node *f;
	if(a->f==root)
        f=a,root=a;
	 else
	    if(a->f->l())
		  a->f->f->lc=a,f=a->f->f;
	else a->f->f->rc=a,f=a->f->f;
	a->lc->f=a->f;
	a->f->rc=a->lc;
	a->f->f=a;
	a->lc=a->f;
	a->f=f;
}
inline void Change(Node *a)
{a->l()?Lc(a):Rc(a);}
inline void TwiChange(Node *a)
{a->l()==a->f->l()?Change(a->f):Change(a);Change(a);}
inline void Rotato(Node *a)
{
     while(a->f!=root)TwiChange(a);
     if(a!=root)Change(a);
}
inline void Rotato2(Node *a)
{
     while(a->f->f!=root)TwiChange(a);
     if(a->f!=root)Change(a);
}
Node* FindPre(ll ax,Node *tp)
{
	Node *res;
	if(tp==empty)return tp;
	if(tp->flag())pushdown(tp);
	if(tp->ax>=ax)return (res=FindPre(ax,tp->lc))==empty?empty:res;
    return (res=FindPre(ax,tp->rc))==empty?tp:res;
}
Node* FindAft(ll ax,Node *tp)
{
    Node *res;
	if(tp==empty)return tp;
	if(tp->flag())pushdown(tp);
	if(tp->ax>ax)return (res=FindAft(ax,tp->lc))==empty?tp:res;
    return (res=FindAft(ax,tp->rc))==empty?empty:res;
}
inline Node* Div(ll l,ll r)
{

    Node *L;
	if((L=FindPre(l,root))!=empty)
	{
	  Rotato(L),Rotato2(FindAft(r,root));
	   return root->rc->lc;
	}
	else
      {
      	  Rotato(FindAft(r,root));
      	  return root->lc;
	  }
}
inline void Oper1()
{
	ll v,l,r;
	read(l),read(r),read(v);
	Node *R=Div(l,r);
	R->k_delta*=v;
	R->add_delta*=v;
	Mod(R);
}
inline void Oper2()
{
	ll v,l,r;
	read(l),read(r),read(v);
	Div(l,r)->add_delta+=v;
}
void Insert(Node *Cache,Node *tp)
{
	if(tp->flag())pushdown(tp);
	if(Cache->ax<tp->ax)
	   if(tp->lc==empty)
	    Cache->f=tp,tp->lc=Cache;
	   else
	      Insert(Cache,tp->lc);
	else
	 if(tp->rc==empty)
	    Cache->f=tp,tp->rc=Cache;
	   else
	      Insert(Cache,tp->rc);
}
inline void Oper3()
{
	ll l,r;
    read(l),read(r);
	Div(l,r)->ax_delta++;
    Node *tp=FindAft(r,root);
	Node *tp2=FindPre(r+2,root);
    tp2->k+=tp->k;
    while(tp->lc!=empty||tp->rc!=empty)
    tp->lc!=empty?Change(tp->lc):Change(tp->rc);
    (tp->l()?tp->f->lc:tp->f->rc)=empty;
     tp->ax=l;
     tp->k=0;
     tp->k_delta=1;
     tp->add_delta=0;
     tp->ax_delta=0;
     Insert(tp,root);
}
ll Query(ll a,ll &tmp,Node *tp)
{
	if(tp==empty)return 0;
    if(tp->flag())pushdown(tp);
	ll res=Query(a,tmp,tp->lc);
	res+=tp->k*1ll*tmp;
	tmp=(a*1ll*tmp)%mod;
	return res=(res+Query(a,tmp,tp->rc))%mod;
}
inline void Oper4()
{
	ll v,tp=1;
	read(v);
	Rotato(&Tree[100001]);
	printf("%lld\n",Query(v,tp,root->lc));
}
ll n;
int main()
{
        begin();	
	read(n);
	while(n--)
	{

		do c=getchar();while(c!='a'&&c!='q'&&c!='m');
		if(c=='a')
		   Oper2();
		else if(c=='m')
		{
			c=getchar();c=getchar();c=getchar();
			if(c=='x')Oper3();
			else Oper1();
		}
		else Oper4();
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值