Happy Birthday 长者!
我还是很颓废啊
1.Luogu P3373 【模板】线段树 2
链接:https://www.luogu.org/problemnew/show/P3373
我太弱了,这题都写,线段树无解释。。。
#pragma GCC optimize("O3")
#include <iostream>
#include <cstdio>
using namespace std;
int p;
long long a[100007];
struct node{
long long v, mul, add;
}st[400007];
void bt(int root, int l, int r){
st[root].mul=1;
st[root].add=0;
if(l==r)
st[root].v=a[l];
else{
int m=(l+r)/2;
bt(root*2, l, m);
bt(root*2+1, m+1, r);
st[root].v=st[root*2].v+st[root*2+1].v;
}
st[root].v%=p;
}
void pushdown(int root, int l, int r){
int m=(l+r)/2;
st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(m-l+1))%p;
st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-m))%p;
st[root*2].mul=(st[root*2].mul*st[root].mul)%p;
st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p;
st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p;
st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p;
st[root].mul=1;
st[root].add=0;
}
void ud1(int root, int stdl, int stdr, int l, int r, long long k){
if(r<stdl || stdr<l)
return ;
if(l<=stdl && stdr<=r){
st[root].v=(st[root].v*k)%p;
st[root].mul=(st[root].mul*k)%p;
st[root].add=(st[root].add*k)%p;
return ;
}
pushdown(root, stdl, stdr);
int m=(stdl+stdr)/2;
ud1(root*2, stdl, m, l, r, k);
ud1(root*2+1, m+1, stdr, l, r, k);
st[root].v=(st[root*2].v+st[root*2+1].v)%p;
}
void ud2(int root, int stdl, int stdr, int l, int r, long long k){
if(r<stdl || stdr<l)
return ;
if(l<=stdl && stdr<=r){
st[root].add=(st[root].add+k)%p;
st[root].v=(st[root].v+k*(stdr-stdl+1))%p;
return ;
}
pushdown(root, stdl, stdr);
int m=(stdl+stdr)/2;
ud2(root*2, stdl, m, l, r, k);
ud2(root*2+1, m+1, stdr, l, r, k);
st[root].v=(st[root*2].v+st[root*2+1].v)%p;
}
long long query(int root, int stdl, int stdr, int l, int r){
if(r<stdl || stdr<l)
return 0;
if(l<=stdl && stdr<=r)
return st[root].v;
pushdown(root, stdl, stdr);
int m=(stdl+stdr)/2;
return (query(root*2, stdl, m, l, r)+query(root*2+1, m+1, stdr, l, r))%p;
}
int main(){
int n, m;
scanf("%d%d%d", &n, &m, &p);
for(int i=1; i<=n; i++)
scanf("%lld", &a[i]);
bt(1, 1, n);
while(m--){
int chk;
scanf("%d", &chk);
int x, y;
long long k;
if(chk==1){
scanf("%d%d%lld", &x, &y, &k);
ud1(1, 1, n, x, y, k);
}
else if(chk==2){
scanf("%d%d%lld", &x, &y, &k);
ud2(1, 1, n, x, y, k);
}
else{
scanf("%d%d", &x, &y);
printf("%lld\n", query(1, 1, n, x, y));
}
}
return 0;
}
2.Luogu P2486 [SDOI2011]染色
链接:https://www.luogu.org/problemnew/show/P2486
树剖板题
#pragma GCCoptimize("O3")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=100+50;
const int MAXN=100000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=100000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int n,m,edge_cnt,cnt,Lc,Rc;
char str[N];
int col[MAXN],head[MAXN],sz[MAXN],dep[MAXN],fa[MAXN],son[MAXN],top[MAXN],pos[MAXN];
struct Edge{
int u,v,next;
}edge[MAXN<<1];
struct node{
int l,r;
int num,tag,lc,rc;
}segtree[MAXN<<2];
inline void init()
{
edge_cnt=cnt=0;
memset(head,-1,sizeof(head));
}
inline void addedge(int u,int v)
{
edge[edge_cnt].u=u; edge[edge_cnt].v=v;
edge[edge_cnt].next=head[u]; head[u]=edge_cnt++;
}
inline void dfs1(int u,int pre,int depth){
sz[u]=1;
fa[u]=pre;
son[u]=0;
dep[u]=depth;
for(register int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v == pre)
continue;
dfs1(v,u,depth+1);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v])
son[u]=v;
}
}
inline void dfs2(int u,int tp){
pos[u]=++cnt;
top[u]=tp;
if(son[u]!=0)
dfs2(son[u],top[u]);
for(register int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v == fa[u] || v == son[u])
continue;
dfs2(v,v);
}
}
inline void push_down(int rt)
{
if(segtree[rt].tag)
{
segtree[L(rt)].tag=segtree[R(rt)].tag=segtree[rt].tag;
segtree[L(rt)].num=segtree[R(rt)].num=1;
segtree[L(rt)].lc=segtree[L(rt)].rc=segtree[rt].lc;
segtree[R(rt)].lc=segtree[R(rt)].rc=segtree[rt].lc;
segtree[rt].tag=0;
}
}
inline void push_up(int rt)
{
segtree[rt].lc=segtree[L(rt)].lc;
segtree[rt].rc=segtree[R(rt)].rc;
int ans=segtree[L(rt)].num+segtree[R(rt)].num;
if(segtree[L(rt)].rc == segtree[R(rt)].lc)
ans--;
segtree[rt].num=ans;
}
inline void build(int rt,int l,int r)
{
segtree[rt].l=l;
segtree[rt].r=r;
segtree[rt].num=0;
if(l == r)
return ;
int mid=(l+r)>>1;
build(L(rt),l,mid);
build(R(rt),mid+1,r);
}
inline void update(int rt,int l,int r,int x){
if(segtree[rt].l == l && segtree[rt].r == r)
{
segtree[rt].num=segtree[rt].tag=1;
segtree[rt].lc=segtree[rt].rc=x;
return ;
}
push_down(rt);
int mid=(segtree[rt].l+segtree[rt].r)>>1;
if(r<=mid)
update(L(rt),l,r,x);
else if(l>mid)
update(R(rt),l,r,x);
else
{
update(L(rt),l,mid,x);
update(R(rt),mid+1,r,x);
}
push_up(rt);
}
inline int query(int rt,int l,int r,int L,int R){
if(segtree[rt].l == L)
Lc=segtree[rt].lc;
if(segtree[rt].r == R)
Rc=segtree[rt].rc;
if(segtree[rt].l == l && segtree[rt].r == r)
return segtree[rt].num;
push_down(rt);
int mid=(segtree[rt].l+segtree[rt].r)>>1;
if(r<=mid)
return query(L(rt),l,r,L,R);
else if(l>mid)
return query(R(rt),l,r,L,R);
else
{
int ans=query(L(rt),l,mid,L,R)+query(R(rt),mid+1,r,L,R);
if(segtree[L(rt)].rc == segtree[R(rt)].lc)
ans--;
return ans;
}
push_up(rt);
}
inline int solve(int u,int v,int id,int c){
int ans=0;
if(id == 1)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
swap(u,v);
update(1,pos[top[u]],pos[u],c);
u=fa[top[u]];
}
if(dep[u]>dep[v])
swap(u,v);
update(1,pos[u],pos[v],c);
}
else
{
int ans1=-1,ans2=-1;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
{
swap(u,v);
swap(ans1,ans2);
}
ans+=query(1,pos[top[u]],pos[u],pos[top[u]],pos[u]);
if(Rc == ans1)
ans--;
ans1=Lc; u=fa[top[u]];
}
if(dep[u]<dep[v]){
swap(u,v);
swap(ans1,ans2);
}
ans+=query(1,pos[v],pos[u],pos[v],pos[u]);
if(Rc == ans1)
ans--;
if(Lc == ans2)
ans--;
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
init();
for(register int i=1;i<=n;++i)
scanf("%d",&col[i]);
for(register int i=1;i<n;++i)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs1(1,1,1);
dfs2(1,1);
build(1,1,n);
for(register int i=1;i<=n;++i)
update(1,pos[i],pos[i],col[i]);
while(m--)
{
scanf("%s",str);
int u,v;
if(str[0] == 'C')
{
int c;
scanf("%d%d%d",&u,&v,&c);
solve(u,v,1,c);
}
else
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",solve(u,v,2,0));
}
}
return 0;
}
3.Luogu P1486 [NOI2004]郁闷的出纳员
链接:https://www.luogu.org/problemnew/show/P1486
可以Splay,但我用了pb_ds的红黑数(逃~
#pragma GCC optimize("O3")
#include<cstdio>
#include<iostream>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
struct node{
int v,id;
node(int a,int b){v=a;id=b;}
bool operator >(node b) const
{return v==b.v?id>b.id:v>b.v;}
};
tree<node,null_type,greater<node>,rb_tree_tag,tree_order_statistics_node_update> T,TE;
int main(){
int n,m,k,s=0,q,ans=0;
char c;
scanf("%d%d",&n,&m);
while(n--)
{
cin>>c;
scanf("%d",&k);
if(c=='I')
{
k+=s;
if(k>=m)
T.insert(node(k,n));
}
else if(c=='A')
m-=k,s-=k;
else if(c=='S')
{
m+=k,s+=k;
T.split(node(m,-1),TE);
ans+=TE.size();
}
else
printf(k>T.size()?"-1\n":"%d\n",T.find_by_order(k-1)->v-s);
}
printf("%d\n",ans);
return 0;
}
4.Luogu P3701 「伪模板」主席树
链接:https://www.luogu.org/problemnew/show/P3701
实际是巧妙的建图+最大流就行(膜蛤)
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define re register
#define inf 500000000
#define s1 b1[i].id[0]
#define s2 b2[j].id[0]
using namespace std;
struct pe
{
int hp;
string id;
};
pe b1[101],b2[101];
struct po
{
int to,nxt,w;
}edge[300001];
int head[20001],cur[200001],num=-1,n,m,t,x,y,s,l,tot,sum,xu1,xu2,dep[20001];
inline int read()
{
int x=0,c=1;
char ch=' ';
while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
while(ch=='-')c*=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*c;
}
inline void add_edge(int from,int to,int w)
{
edge[++num].nxt=head[from];
edge[num].to=to;
edge[num].w=w;
head[from]=num;
}
inline void add(int from,int to ,int w)
{
add_edge(from,to,w);
add_edge(to,from,0);
}
inline bool bfs()
{
memset(dep,0,sizeof(dep));
queue<int> q;
while(!q.empty())
q.pop();
dep[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
for(re int i=head[u];i!=-1;i=edge[i].nxt)
{
int v=edge[i].to;
if(edge[i].w>0&&dep[v]==0)
{
dep[v]=dep[u]+1;
if(v==t)
return 1;
q.push(v);
}
}
}
return 0;
}
inline int dfs(int u,int dis)
{
if(u==t)
return dis;
int diss=0;
for(re int& i=cur[u];i!=-1;i=edge[i].nxt)
{
int v=edge[i].to;
if(edge[i].w!=0&&dep[v]==dep[u]+1)
{
int check=dfs(v,min(dis,edge[i].w));
if(check)
{
diss+=check;
dis-=check;
edge[i].w-=check;
edge[i^1].w+=check;
if(dis==0)
break;
}
}
}
return diss;
}
inline int dinic()
{
int ans=0;
while(bfs())
{
for(re int i=s;i<=t;++i)
cur[i]=head[i];
while(int d=dfs(s,inf))
ans+=d;
}
return ans;
}
inline int pd1(int x)
{
if(b1[x].id[0]=='J')
return xu1;
else
return 0;
}
inline int pd2(int x)
{
if(b2[x].id[0]=='J')
return xu2;
else
return 0;
}
int main()
{
memset(head,-1,sizeof(head));
n=read();m=read();
for(re int i=1;i<=n;++i)
cin>>b1[i].id;
for(re int i=1;i<=n;++i)
cin>>b2[i].id;
for(re int i=1;i<=n;++i)
cin>>b1[i].hp;
for(re int i=1;i<=n;++i)
cin>>b2[i].hp;
for(re int i=1;i<=n;++i)
{
if(b1[i].id[0]=='Y')
xu1++;
if(b2[i].id[0]=='Y')
xu2++;
}
s=0;
t=2*n+1;
for(re int i=1;i<=n;++i)
for(re int j=1;j<=n;++j)
{
if(s1=='J'&&(s2=='H'||s2=='W'))
add(i,j+n,1);
if(s1=='E'&&(s2=='J'||s2=='Y'))
add(i,j+n,1);
if(s1=='Y'&&(s2=='J'||s2=='H'))
add(i,j+n,1);
if(s1=='H'&&(s2=='E'||s2=='W'))
add(i,j+n,1);
if(s1=='W'&&(s2=='Y'||s2=='E'))
add(i,j+n,1);
}
for(re int i=1;i<=n;++i)
add(s,i,b1[i].hp+pd1(i)),add(i+n,t,b2[i].hp+pd2(i));
cout<<min(dinic(),m);
}
5.Luogu P3258 [JLOI2014]松鼠的新家
链接:https://www.luogu.org/problemnew/show/P3258
树剖板题
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;
struct node{
int to,next;
}e[600005];
int head[300005],num=0;
inline void add(int x,int y)
{
e[++num].to=y;
e[num].next=head[x];
head[x]=num;
}
int n,route[300005];
int son[300005],fa[300005],size[300005],l[300005],top[300005],dep[300005],tot=0;
int sum[1200005],tag[1200005];
int cnt=1,pos[300005];
inline void update(int x,int l,int r,int L,int R,int v)
{
if(R<l||r<L)
return;
if(L<=l&&r<=R)
{
sum[x]+=(r-l+1)*v;
tag[x]+=v;
return;
}
int mid=(l+r)>>1;
update(x<<1,l,mid,L,R,v);
update(x<<1|1,mid+1,r,L,R,v);
sum[x]=sum[x<<1]+sum[x<<1|1];
}
inline void pushdown(int x,int l,int r)
{
if(l==r)
{
pos[cnt++]=x;
return;
}
int mid=(l+r)>>1;
int ls=x<<1;
int rs=ls+1;
if(tag[x])
{
sum[ls]+=(mid-l+1)*tag[x];
sum[rs]+=(r-mid)*tag[x];
tag[ls]+=tag[x];
tag[rs]+=tag[x];
tag[x]=0;
}
pushdown(ls,l,mid);
pushdown(rs,mid+1,r);
}
inline void cal(int x,int y)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy])
{
swap(x,y);
swap(fx,fy);
}
update(1,1,tot,l[fx],l[x],1);
x=fa[fx];
fx=top[x];
}
if(l[x]>l[y])
swap(x,y);
update(1,1,tot,l[x],l[y],1);
}
inline void dfs1(int s)
{
size[s]=1;
for(register int i=head[s];i;i=e[i].next)
{
int v=e[i].to;
if(!dep[v])
{
dep[v]=dep[s]+1;
fa[v]=s;
dfs1(v);
size[s]+=size[v];
if(size[son[s]]<size[v])
son[s]=v;
}
}
}
inline void dfs2(int x,int t)
{
l[x]=++tot;
top[x]=t;
if(son[x])
dfs2(son[x],t);
for(register int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v!=fa[x]&&v!=son[x])
dfs2(v,v);
}
}
int main()
{
scanf("%d",&n);
for(register int i=1;i<=n;++i)
scanf("%d",&route[i]);
for(register int i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
fa[1]=1;dep[1]=1;
dfs1(1);
dfs2(1,1);
memset(sum,0,sizeof(sum));
memset(tag,0,sizeof(tag));
for(register int i=1;i<n;++i)
{
cal(route[i],route[i+1]);
update(1,1,tot,l[route[i+1]],l[route[i+1]],-1);
}
pushdown(1,1,tot);
for(register int i=1;i<=n;++i)
cout<<sum[pos[l[i]]]<<"\n";
return 0;
}
还是膜蛤好!!!
江来是要负泽任的,民不民白啊!
滋不滋磁啊!
坠吼坠吼的啊!
港记和美国的华莱士!
请不要思想江化!
我们要膜蛤,当一名hath