数据结构刷题题单

数据结构刷题题单

这是一份来自 p_b_p_b 大佬的题单,但是未完待续啊(我没做完555)。。

题目

CF1132G

link

  • 对于每一个元素,若选择它,那么下一个选择的数是固定的,我们发现这个一个森林的结构,我们在第 n + 1 n+1 n+1的位置上再建一个树根,它就变成了一个树形结构
  • 我们先把树建出来,考虑加点删点对答案的影响,每加入一个数,它子树内的所有节点答案加一,每删除一个数,它子树内所有节点答案减一
  • 这两个操作在 d f s dfs dfs序上是连续的,于是在 d f s dfs dfs序上用线段树维护,区间加减一,和最大值即可

bzoj4025 二分图

link

  • 一个图是二分图的充要条件是不存在奇环
  • 在时间轴上维护线段树,按时间分治,将所有的边插入到被它完全覆盖的线段树节点上
  • 用按秩合并的并査集来维护点之间的距离(只记录奇偶),对于每个节点,将其上面所有的边连上,若出现奇环,那么这个区间所有的时刻都不是二分图,回溯那次离开每个节点的时候撤销在这个节点上的所有连边操作

CF848C

link

  • 某个区间内最后一次出现减去第一次出现的条件,给它做一个类似差分的思想,考虑每一个位置 i i i,设 a i a_i ai这个数上次出现的位置是 p r e i pre_i prei,那么区间询问的答案就是 ∑ p r e i ≥ l , i ∈ [ l , r ] i − p r e i \sum_{pre_i \geq l,i \in [l,r]}i-pre_i preil,i[l,r]iprei
  • 我们把每个位置的贡献看作一个点 ( i , p r e i ) (i,pre_i) (i,prei),这个点的权值为 i − p r e i i-pre_i iprei,那么一个 [ l , r ] [l,r] [l,r]的询问就是在求二维平面上 [ l , l ] [l,l] [l,l] [ r , r ] [r,r] [r,r]这个矩形的点权和,再算上时间轴那一维,就是三维偏序了,第一维按时间摆好,第二维 x x x轴归并排序,第三维 y y y轴开一个支持单点修改区间查询的树状数组
  • 对于每次修改点权变动的点只有旧颜色的前驱后继,新颜色的前驱后继,我们加上新的点把要删除的抵消,把要加入的加上
  • 对于每次询问,我们可以把它差分成四个左下角是 [ 1 , 1 ] [1,1] [1,1]的询问,但是 p b pb pb说不用差分就不用差分! 我们发现 p r e i < i pre_i<i prei<i所以我们相当于求矩形 [ 1 , l ] [1,l] [1,l] [ r , n ] [r,n] [r,n]的点权和,这就变成两个前缀和相减咯

正睿2019暑假D3T3

link

  • 我们关注一条边,当它关上的那一刻之前,两边的联通块的信息必然相容,这很显然,当它再次打开的时候两边的联通块信息在再次互补,但是上次已经交流过的信息不会产生贡献,那我们设两个联通块这是的信息量分别是 v a l 1 , v a l 2 val_1,val_2 val1,val2,这条边上次关闭前它们的共同信息量是 l a s t last last,那么当这条边再次打开的时候,这整个联通块的信息量会变成 v a l 1 + v a l 2 − l a s t val_1+val_2-last val1+val2last
  • 所以我们并不用维护每个点有的信息具体是些什么,只要维护每个联通块掌握的信息量即可
  • 那么我们将这个信息量维护在原树上深度最低的那个点上,然后就可以了

CF576E

link

  • 这是bzoj二分图的加强版,对于多个颜色的情况类似
  • 我们处理出每次修改可能维持影响的时间区间,按照这个时间区间将这条边在线段树上插入对应的点
  • 每次在线段树上搜到叶子节点时判断yes or no的同时将这条边的颜色确定,和二分图那题一样用按秩合并的并査集维护即可

CF1136E

link

  • 这题的思路就是等价转化一下操作,使得它方便维护
  • g i = ∑ j = 1 i k i g_i= \sum_{j=1}^i k_i gi=j=1iki,那么 a i ≥ a i − 1 + k i − 1 累 加 得 a i ≥ a 1 + g i − 1 a_i \ge a_{i-1}+ k_{i-1}累加得a_i \ge a_{1}+g_{i-1} aiai1+ki1aia1+gi1
  • 再令 u i = a i − g i − 1 , 那 么 由 于 a i ≥ a i − 1 + k i − 1 , 所 以 u i + g i − 1 ≥ u i − 1 + g i − 2 + k i − 1 , 即 u i + g i − 1 ≥ u i − 1 + g i − 1 即 u i ≥ u i − 1 u_i=a_i-g_{i-1},那么由于a_i \ge a_{i-1}+k_{i-1},所以u_i+g_{i-1} \ge u_{i-1}+g_{i-2}+k_{i-1},即u_i+g_{i-1} \ge u_{i-1}+g_{i-1}即u_i\ge u_{i-1} ui=aigi1,aiai1+ki1,ui+gi1ui1+gi2+ki1,ui+gi1ui1+gi1uiui1,于是就发现操作等价于维护 u i u_{i} ui单调不降
  • 那么我们每次修改时只需二分一下需要修改多少个才能使 u i u_i ui不降即可

代码

CF1132G 代码

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
using namespace std;
const int N=2e6+5;
int n,k,a[N],ans[N],stck[N],top=0;
int tot=0,f[N],nxt[N<<1];
int dfnn=0,dfn[N],siz[N],t[N<<2],tag[N<<2],fa[N];
struct E
{
	int u,v;
}e[N<<1];
void Add(int u,int v)
{
	tot++;
	nxt[tot]=f[u];
	f[u]=tot;
	e[tot]=(E){u,v};
	return;
}
void DFS(int u)
{
	dfn[u]=++dfnn;
	siz[u]=1;
	for(register int j=f[u];j!=-1;j=nxt[j])
	{
		int v=e[j].v;
		if (v==fa[u]) continue;
		fa[v]=u;
		DFS(v);
		siz[u]+=siz[v];
	}
	return;
}
void push(int p,int l,int r)
{
	int mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	if (!tag[p]) return;
	t[ls]+=tag[p];
	t[rs]+=tag[p];
	tag[ls]+=tag[p];
	tag[rs]+=tag[p];
	tag[p]=0;
	return;
}
void mdf(int p,int l,int r,int L,int R,int val)
{
	if (L<=l&&r<=R)
	{
		t[p]+=val;
		tag[p]+=val;
		return;
	}
	int mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	push(p,l,r);
	if (L<=mid) mdf(ls,l,mid,L,R,val);
	if (R>mid) mdf(rs,mid+1,r,L,R,val);
	t[p]=max(t[ls],t[rs]);
	return;
}
int main()
{
	memset(f,-1,sizeof(f));
	scanf("%d%d",&n,&k);
	FOR(i,1,n) scanf("%d",&a[i]);
	a[++n]=n+1;
	FOR(i,1,n)
	{
		while (top&&a[stck[top]]<a[i]) Add(stck[top],i),Add(i,stck[top]),top--;
		stck[++top]=i;
	}
	DFS(n);
	FOR(i,1,k) mdf(1,1,n,dfn[i],dfn[i]+siz[i]-1,1);
	ans[++ans[0]]=t[1];
	FOR(i,k+1,n-1)
	{
		mdf(1,1,n,dfn[i-k],dfn[i-k]+siz[i-k]-1,-1);
		mdf(1,1,n,dfn[i],dfn[i]+siz[i]-1,1);
		ans[++ans[0]]=t[1];
	}
	FOR(i,1,ans[0]) printf("%d ",ans[i]);
	return 0;
}

bzoj4125二分图 代码

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define pb push_back
using namespace std;
const int N=2e5+5;
int n,m,T,ans[N],fa[N],d[N],dep[N];
struct E
{
    int u,v,w;
};
vector <E> G[N<<2];
int read()
{
    int x=0,f=1;
    char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    return f*x;
}
void Insert(int p,int l,int r,int L,int R,int u,int v)
{
    if (L<=l&&r<=R)
    {
        G[p].pb((E){u,v,0});
        return;
    }
    int mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
    if (L<=mid) Insert(ls,l,mid,L,R,u,v);
    if (R>mid) Insert(rs,mid+1,r,L,R,u,v);
    return;
}
int Getfa(int x)
{
    if (fa[x]==x) return x;
    else return Getfa(fa[x]);
}
int Getdis(int x)
{
    if (fa[x]==x) return 0;
    else return d[x]^Getdis(fa[x]);
}
void Del(vector<E> trash)
{
    int len=trash.size();
    FOR(i,0,len-1)
    {
        int u=trash[i].u,v=trash[i].v,w=trash[i].w;
        fa[u]=u;
        d[u]=0;
        dep[v]-=w;
    }
    return;
}
void Solve(int p,int l,int r)
{
    vector <E> trash;
    trash.clear();
    int len=G[p].size();
    FOR(i,0,len-1)
    {
        int u=G[p][i].u,v=G[p][i].v;
        int fu=Getfa(u),fv=Getfa(v),dis=Getdis(u)^Getdis(v)^1;
        if (fu==fv&&dis)
        {
            FOR(j,l,r) ans[j]=0;
            Del(trash);
            return;
        }
        if (fu!=fv) 
        {
            if (dep[fu]>dep[fv]) swap(fu,fv),swap(u,v);
            fa[fu]=fv;
            d[fu]=dis;
            if (dep[fu]==dep[fv]) dep[fv]++,trash.pb((E){fu,fv,1});
            else trash.pb((E){fu,fv,0});
        }
    }
    if (l==r) 
    {
        Del(trash);
        ans[l]=1;
        return;
    }
    int mid=(l+r)>>1;
    Solve(p<<1,l,mid);
    Solve(p<<1|1,mid+1,r);
    Del(trash);
    return;
}
int main()
{
    n=read(),m=read(),T=read();
    FOR(i,1,n) fa[i]=i;
    FOR(i,1,m)
    {
        int u=read(),v=read(),st=read()+1,ed=read();
        Insert(1,1,T,st,ed,u,v);
    }
    Solve(1,1,T);
    FOR(i,1,T) 
        if (ans[i]) printf("Yes\n");
        else printf("No\n");
    return 0;
}

CF848C 代码

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
using namespace std;
typedef long long ll;
const int N=2e6+5;
int n,m,a[N],pos[N],pre[N],tpp=0,opt,tmp1,tmp2;
ll t[N],ans[N];
set <int> s[N];
set <int> :: iterator it;
struct data
{
	int x,y,opt;
	ll val;
}A[N],B[N];
inline int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
inline void Del(int x)
{
	it=s[a[x]].find(x);
	int pr=0,nx=0;
	it++;
	if (it!=s[a[x]].end()) nx=*it;
	it--;
	if (it!=s[a[x]].begin())
	{
		it--;
		pr=*it;
		it++;
	}
	A[++tpp]=(data){x,pr,1,pr-x};
	if (nx)
	{
		A[++tpp]=(data){nx,pre[nx],1,pre[nx]-nx};
		pre[nx]=pr;
		A[++tpp]=(data){nx,pre[nx],1,nx-pre[nx]};
	}
	s[a[x]].erase(*it);
	return;
}
inline void Insert(int x,int v)
{
	a[x]=v;
	s[v].insert(x);
	it=s[v].find(x);
	int nx=0,pr=0;
	it++;
	if (it!=s[v].end()) nx=*it;
	it--;
	if (it!=s[v].begin())
	{
		it--;
		pr=*it;
		it++;
	}
	A[++tpp]=(data){x,pr,1,x-pr};
	pre[x]=pr;
	if (nx)
	{
		A[++tpp]=(data){nx,pr,1,pr-nx};
		pre[nx]=x;
		A[++tpp]=(data){nx,x,1,nx-x};
	}
	return;
}
inline void Input()
{
	n=read(),m=read();
	FOR(i,1,n)
	{
		a[i]=read();
		s[a[i]].insert(i);
		pre[i]=pos[a[i]];
		pos[a[i]]=i;
		A[++tpp]=(data){i,pre[i],1,i-pre[i]};
	}
	FOR(i,1,m)
	{
		opt=read(),tmp1=read(),tmp2=read();
		switch (opt)
		{
			case 1:
				Del(tmp1);
				Insert(tmp1,tmp2);
				break;
			case 2:
				ans[0]++;
				A[++tpp]=(data){tmp1-1,tmp1-1,2,ans[0]};
				A[++tpp]=(data){tmp2,tmp2,2,ans[0]};
				A[++tpp]=(data){tmp1-1,tmp2,2,-ans[0]};
				A[++tpp]=(data){tmp2,tmp1-1,2,-ans[0]};
				break;
		}
	}
	return;
}
inline int lowbit(int x) 
{
	return x&-x;
}
inline void Update(int x,ll v)
{
	for (register int i=x;i<=n+1;i+=lowbit(i))
		t[i]+=v;
	return;
}
inline ll Query(int x)
{
	ll ret=0;
	for (register int i=x;i;i-=lowbit(i))
		ret+=t[i];
	return ret;
}
inline void CDQ(int l,int r)
{
	if (l==r) return;
	int mid=(l+r)>>1;
	CDQ(l,mid),CDQ(mid+1,r);
	int ql=l,qr=mid+1,tmp=l-1;
	while (qr<=r)
	{
		while (ql<=mid&&A[ql].x<=A[qr].x)
		{
			if (A[ql].opt==1) Update(A[ql].y,A[ql].val);
			B[++tmp]=A[ql++];
		}
		if (A[qr].opt==2)
		{
			if (A[qr].val>0) ans[A[qr].val]+=Query(A[qr].y);
			else ans[-A[qr].val]-=Query(A[qr].y);
		}
		B[++tmp]=A[qr++];
	}
	FOR(i,l,ql-1) if (A[i].opt==1) Update(A[i].y,-A[i].val);
	while (ql<=mid) B[++tmp]=A[ql++];
	FOR(i,l,r) A[i]=B[i];
//	FOR(i,1,n) printf("%d ",t[i]);
//	printf("\n");
	return;
}
int main()
{
//	freopen("data.in","r",stdin);
//	freopen("myans.out","w",stdout);
	Input();
	FOR(i,1,tpp) A[i].x++,A[i].y++;
//	FOR(i,1,tpp) printf("%d %d %d %d\n",A[i].x,A[i].y,A[i].opt,A[i].val);
	CDQ(1,tpp);
	FOR(i,1,ans[0]) printf("%lld\n",ans[i]);
	return 0;
}

正睿2019暑假D3T3 代码

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
using namespace std;
const int N=2e5+5;
int n,m,q,u[N],v[N];
int pre[N],ch[N][2],rev[N];
int query[N],ans[N],val[N],opt[N],now[N],last[N];
//把联通块的信息维护在了原树深度最浅的点的val上 
//所以所有破坏树结构的操作(带makeroot) 都要重新调整val的位置 
//当然pb大佬教我的不破坏树结构的方法踩了我一百毫秒 
int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}

int nroot(int x) {return ch[pre[x]][0]==x||ch[pre[x]][1]==x;}
void Update_rev(int p) {if (!p) return;swap(ch[p][0],ch[p][1]);rev[p]^=1;return;}
void Push(int p) {if (!rev[p]) return;if (!rev[p]) return;Update_rev(ch[p][0]);Update_rev(ch[p][1]);rev[p]=0;return;}
void Rotate(int x)
{
	int y=pre[x],k=(ch[y][0]==x);
	ch[y][!k]=ch[x][k];
	if (ch[x][k]) pre[ch[x][k]]=y;
	if (pre[y]&&nroot(y)) ch[pre[y]][(ch[pre[y]][1]==y)]=x;
	pre[x]=pre[y];
	pre[y]=x;
	ch[x][k]=y;
	return;
}
void Pushall(int x)
{
	if (nroot(x)) Pushall(pre[x]);
	Push(x);
	return;
}
void Splay(int x)
{
	Pushall(x);
	while (nroot(x))
	{
		int y=pre[x],z=pre[y];
		if (nroot(y))
		{
			if ((ch[z][1]==y)xor(ch[y][1]==x)) Rotate(x);
			else Rotate(y);
		}
		Rotate(x);
	}
	return;
}
void Access(int x)
{
	int y=0;
	for (;x;x=pre[y=x])
	{
		Splay(x);
		ch[x][1]=y;
	}
	return;
}
int Getrt(int x)
{
	Access(x);
	Splay(x);
	while (ch[x][0]) x=ch[x][0];
	Splay(x);
	return x;
}
void Make_root(int x)
{
	int tmpval=val[Getrt(x)];
	Access(x);
	Splay(x);
	Update_rev(x);
	val[x]=tmpval;
	return;
}
void Link(int u,int v)
{
	Make_root(u);
	pre[u]=v;
	return;
}
void Cut(int u,int v)
{
	int tmpval=val[Getrt(u)];
	Make_root(u);
	Access(v);
	Splay(v);
	pre[u]=ch[v][0]=0;
	val[Getrt(u)]=val[Getrt(v)]=tmpval;
	return;
}
int main()
{
	n=read(),m=read(),q=read();
	FOR(i,1,n-1) u[i]=read(),v[i]=read();
	FOR(i,1,m) opt[i]=read();
	FOR(i,1,q) query[i]=read();
	FOR(i,1,n) val[i]=1;
	FOR(i,1,m)
	{
		if (!now[opt[i]])
		{
			int v1=val[Getrt(u[opt[i]])],v2=val[Getrt(v[opt[i]])];
			Link(u[opt[i]],v[opt[i]]);
			val[Getrt(u[opt[i]])]=v1+v2-last[opt[i]];
		}
		else
		{
			last[opt[i]]=val[Getrt(u[opt[i]])];
			Cut(u[opt[i]],v[opt[i]]);
		}
		now[opt[i]]^=1;
	}
	FOR(i,1,q) ans[i]=val[Getrt(query[i])];
	FOR(i,1,q) printf("%d\n",ans[i]);
	return 0;
}

CF576E 代码

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
#define mem(i,j) memset(i,j,sizeof(i))
#define MP make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
const int N=5e5+5;
const int K=55;
int n,m,k,q,tmp1,tmp2,in1[N],in2[N],last[N],ll[N],rr[N],ans[N];
int fa[K][N],dep[K][N],dis[K][N];
vector <int> vec[N<<2];
struct data
{
	int u,v,col,w;
}e[N];
inline int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
inline void write(int x)
{
	if (x<0) putchar('-'),x=-x;
	if (x>9) write(x/10);
	putchar(x%10+'0');
	return;
}
inline int getfa(int col,int x) {return (fa[col][x]==x)?x:getfa(col,fa[col][x]);}
inline int getdis(int col,int x) {return (fa[col][x]==x)?0:(getdis(col,fa[col][x]) xor dis[col][x]);}
inline relation(int col,int u,int v)
{
	int fu=getfa(col,u),fv=getfa(col,v);
	return (fu==fv);
}
inline data merge(int col,int u,int v)
{
	int fu=getfa(col,u),fv=getfa(col,v);
	data ret=(data){fu,fv,col,0};
	if (dep[col][fu]>dep[col][fv]) swap(u,v),swap(fu,fv),swap(ret.u,ret.v);
	int tmp_dis=getdis(col,u) xor getdis(col,v) xor 1;
	dis[col][fu]=tmp_dis;
	fa[col][fu]=fv;
	if (dep[col][fu]==dep[col][fv]) dep[col][fv]++,ret.w=1;
	return ret;
}
inline void del(stack <data> stck)
{
	while (stck.size())
	{
		data tmp=stck.top();
		stck.pop();
		int fu=tmp.u,fv=tmp.v,col=tmp.col,w=tmp.w;
		dep[col][fv]-=w;
		fa[col][fu]=fu;
		dis[col][fu]=0;
	}
	return;
}
inline void insert(int p,int l,int r,int L,int R,int num)
{
	if (L<=l&&r<=R)
	{
		vec[p].pb(num);
		return;
	}
	int mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	if (L<=mid) insert(ls,l,mid,L,R,num);
	if (R>mid) insert(rs,mid+1,r,L,R,num);
	return;
}
inline void solve(int p,int l,int r)
{
	stack <data> stck;
	while (stck.size()) stck.pop();
	if (l>r) return;
	FOR(i,0,(int)vec[p].size()-1)
	{
		data tmp_e=e[vec[p][i]];
		int u=tmp_e.u,v=tmp_e.v,col=tmp_e.col;
		if (!col) continue;
		if (relation(col,u,v)) continue;
		stck.push(merge(col,u,v));
	}
	if (l==r)
	{
		data tmp_e=e[in1[l]];
		int judge1=getdis(in2[l],tmp_e.u) xor getdis(in2[l],tmp_e.v) xor 1;
		int judge2=relation(in2[l],tmp_e.u,tmp_e.v);
		if (judge1&&judge2) ans[l]=0;
		else 
		{
			e[in1[l]].col=in2[l];
			ans[l]=1;
		}
		del(stck);
		return;
	}
	int mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	solve(ls,l,mid);
	solve(rs,mid+1,r);
	del(stck);
	return;
}
int main()
{
//	freopen("data.in","r",stdin);
	n=read(),m=read(),k=read(),q=read();
	FOR(i,1,m) tmp1=read(),tmp2=read(),e[i]=(data){tmp1,tmp2,0,0};
	FOR(i,1,q)
	{
		tmp1=read(),tmp2=read();
		in1[i]=tmp1,in2[i]=tmp2;
		if (last[tmp1]) rr[last[tmp1]]=i-1;
		last[tmp1]=i;
		ll[i]=i+1;
		rr[i]=q;
	}
	FOR(i,1,k) FOR(j,1,n) fa[i][j]=j;
	FOR(i,1,q) if (ll[i]<=rr[i]) insert(1,1,q,ll[i],rr[i],in1[i]);
	solve(1,1,q);
	FOR(i,1,q)
	{
		if (ans[i]) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

CF1136E 代码

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
#define For(i,a,b) for (register ll i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define GO(u) for (register ll j=f[u];j!=-1;j=nxt[j])
using namespace std;
typedef long long ll;
const ll N=4e5+5;
ll n,a[N],k[N],q,tmp1,tmp2,ans[N],pos,tmp;
ll g[N],f[N];
char s[2];
ll t[N<<2],tag[N<<2],sum[N<<2],vis[N];
inline ll read()
{
	ll x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
inline void write(ll x)
{
	if (x<0) putchar('-'),x=-x;
	if (x>9) write(x/10);
	putchar(x%10+'0');
	return;
}
inline void bd(ll p,ll l,ll r)
{
	tag[p]=0;
	vis[p]=0;
	if (l==r)
	{
		t[p]=a[l]-g[l-1];
		sum[p]=t[p];
		return;
	}
	ll mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	bd(ls,l,mid);
	bd(rs,mid+1,r);
	sum[p]=sum[ls]+sum[rs];
	return;
}
inline void down(ll p,ll l,ll r)
{
	if (!vis[p]) return;
	ll mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	tag[ls]=tag[p];
	tag[rs]=tag[p];
	t[ls]=t[rs]=tag[p];
	sum[ls]=(mid-l+1)*tag[p];
	sum[rs]=(r-mid)*tag[p];
	vis[ls]=vis[rs]=1;
	vis[p]=0;
	tag[p]=0;
	return;
}
inline ll query(ll p,ll l,ll r,ll L,ll R)
{
	if (L<=l&&r<=R) return sum[p];
	ll mid=(l+r)>>1,ls=p<<1,rs=p<<1|1,ret=0;
	down(p,l,r);
	if (L<=mid) ret+=query(ls,l,mid,L,R);
	if (R>mid) ret+=query(rs,mid+1,r,L,R);
	sum[p]=sum[ls]+sum[rs];
	return ret;
}
inline void md(ll p,ll l,ll r,ll L,ll R,ll v)
{
	if (L<=l&&r<=R)
	{
		vis[p]=1;
		tag[p]=v;
		t[p]=v;
		sum[p]=(r-l+1)*v;
		return;
	}
	ll mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	down(p,l,r);
	if (L<=mid) md(ls,l,mid,L,R,v);
	if (R>mid) md(rs,mid+1,r,L,R,v);
	sum[p]=sum[ls]+sum[rs];
	return;
}
inline ll find(ll l,ll val)
{
	ll L=l,R=n,MID;
	while (L<R)
	{
		MID=(L+R+1)>>1;
		if (query(1,1,n,MID,MID)>val) R=MID-1;
		else L=MID;
	}
	return L;
}
int main()
{
//	freopen("data.in","r",stdin);
	n=read();
	FOR(i,1,n) a[i]=read();
	FOR(i,1,n-1) k[i]=read();
	FOR(i,1,n-1) g[i]=g[i-1]+k[i];
	FOR(i,1,n-1) f[i]=f[i-1]+g[i];
	q=read();
	bd(1,1,n);
	while (q--)
	{
		scanf("%s",s+1);
		tmp1=read(),tmp2=read();
		switch (s[1])
		{
			case 's':
				ans[++ans[0]]=query(1,1,n,tmp1,tmp2)+f[tmp2-1]-f[tmp1-2];
				break;
			case '+':
				tmp=query(1,1,n,tmp1,tmp1);
				tmp+=tmp2;
				pos=find(tmp1,tmp);
				md(1,1,n,tmp1,pos,tmp);
				break;
		}
	}
	FOR(i,1,ans[0]) write(ans[i]),putchar('\n');
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值