loj 2011
题意:一棵树 有两种操作 1.选定一个点 且这个点的权值随着时间的增加而增加1
2.查询一条路径上点的个数和权值大于C的个数
题解:刚开始没想到离线的做法 认为可以大力线段树 n(logn)^3 然而显然过不去 被韦神教育后也考虑过树上莫队的写法 然而n^(5/3)然并卵 偷偷瞄了一眼题解
发现我们可以这样离线一下 然后少掉一个log 对于每个querty我们找到临界位置max(0,i-C-1) 这样的话 我们只要去找当临界位置的时候在这条链上的被更新的点的个数 这样的话 我们树状数组维护就ojbk了
#include
#define ll long long
#define s second
#define f first
#define pii pair
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=2e5+10;
using namespace std;
vectorvec[MAXN];
int son[MAXN],fa[MAXN],num[MAXN],dep[MAXN];
int n,q;
void dfs1(int v,int pre,int deep){
num[v]=1;dep[v]=deep+1;fa[v]=pre;
for(int i=0;i0;i-=get_id(i)) ans+=d[i];
return ans;
}
typedef struct node{
int u,v,id,p;
friend bool operator<(node aa,node bb){
return aa.pdep[v]) swap(u,v);
ans+=(p[v]-p[u]+1);
return ans;
}
int get2(int u,int v){
int uu=tp[u];int vv=tp[v];
int ans=0;
while(uu!=vv){
if(dep[uu]dep[v]) swap(u,v);
ans+=(querty(p[v])-querty(p[u]-1));
return ans;
}
node que[MAXN];
bool pd[MAXN];
pii ans1[MAXN];
int vis[MAXN];
int main(){
scanf("%d",&n);int rt;
int t;
for(int i=1;i<=n;i++){
scanf("%d",&t);son[i]=-1;
if(t==0){
rt=i;continue;
}
vec[i].push_back(t);
vec[t].push_back(i);
}cnt=0;
int cnt1=0;
dfs1(rt,0,0);dfs2(rt,rt);
scanf("%d",&q);
int op,u,v,c;
for(int i=1;i<=q;i++){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&u,&v,&c);
ans1[i].f=get1(u,v);
que[++cnt1].u=u;que[cnt1].v=v;que[cnt1].p=max(0,i-c-1);que[cnt1].id=i;
}
else{
scanf("%d",&u);
if(pd[u]) continue;
vis[i]=u;pd[u]=1;
}
}
sort(que+1,que+cnt1+1);
int _=1;
for(int i=0;i<=q;i++){
if(vis[i]) add(p[vis[i]]);
for(;_<=cnt1&&que[_].p==i;_++){
ans1[que[_].id].s=get2(que[_].u,que[_].v);
}
}
// if(_<=cnt1){
// for(;_<=cnt1;_++){
// ans1[que[_].id].s=get2(que[_].u,que[_].v);
// }
// }
for(int i=1;i<=q;i++)if(!vis[i]) printf("%d %d\n",ans1[i].f,ans1[i].s);
return 0;
}
loj 558
题意:有一个森林 初始时刻每个点都是白色的 现在有四种操作
1.对于u颜色反转
2.连接u,v
3.断开u,v
4.查询与u联通的所有黑点到u的距离的和
题解:大概很巧妙的是LCT维护子树信息 然后维护LCT维护当前节点的这段链上的贡献 注意反转的时候交换就行了 (但是这个题很毒 指针版本的LCT会A掉 然而数组版本的会T 虽然数组版本的没有A掉 就当作练习了
#include
#include
#include
#include
#define pii pair
#define il inline
#define f first
#define s second
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define ll long long
#define rg register
const int MAXN=5e5+10;
using namespace std;
il int read() {
rg int x=0,f=1;
rg char ch=getchar();
while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int ch[MAXN][2],cnt,res[MAXN],pre[MAXN],st[MAXN],tp;
ll sum[MAXN],chsum[MAXN],ke[MAXN],rsum[MAXN],num[MAXN],chnum[MAXN],vul[MAXN],size[MAXN];
bool rt[MAXN],key[MAXN];
il void reverse(int r) {
if(!r) return ;
std::swap(ch[r][0],ch[r][1]);
std::swap(sum[r],rsum[r]);
res[r]^=1;
}
il void push(int x) {
if(res[x]) {
reverse(ch[x][0]);
reverse(ch[x][1]);
res[x]=0;
}
}
il void up(int x) {
if(!x) return ;
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
num[x]=num[ch[x][0]]+num[ch[x][1]]+chnum[x]+key[x];
vul[x]=vul[ch[x][0]]+vul[ch[x][1]]+ke[x];
rsum[x]=rsum[ch[x][0]]+rsum[ch[x][1]]+chsum[x]+1ll*(vul[ch[x][1]]+ke[x])*(num[ch[x][0]]+chnum[x]+key[x]);
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+chsum[x]+1ll*(vul[ch[x][0]]+ke[x])*(num[ch[x][1]]+chnum[x]+key[x]);
}
il void P(int x) {
rg int i;
st[++tp]=x;
for(i=x; !rt[i]; i=pre[i]) st[++tp]=pre[i];
for(; tp; tp--) push(st[tp]);
}
il void rotate(int x,int kind) {
rg int y=pre[x];
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
if(rt[y]) rt[x]=1,rt[y]=0;
else ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];
ch[x][kind]=y;
pre[y]=x;
up(y);
}
il void splay(int x) {
P(x);
while(!rt[x]) {
if(rt[pre[x]]) rotate(x,ch[pre[x]][0]==x);
else {
rg int y=pre[x];
rg int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind);
else rotate(y,kind),rotate(x,kind);
}
}
up(x);
}
il void access(int x) {
rg int y=0;
while(x) {
splay(x);
if(ch[x][1]) {
rt[ch[x][1]]=1;
pre[ch[x][1]]=x;
chsum[x]+=sum[ch[x][1]];
chnum[x]+=num[ch[x][1]];
}
if(y) rt[y]=0,chsum[x]-=sum[y],chnum[x]-=num[y];
ch[x][1]=y;
up(x);
y=x;
x=pre[x];
}
}
il void mroot(int u) {
access(u);
splay(u);
reverse(u);
}
il void Link(int u,int v) {
mroot(u);
mroot(v);
pre[u]=v;
chnum[v]+=num[u];
chsum[v]+=sum[u];
up(v);
}
il void destory(int u,int v) {
//if(!pd(u,v)) return ;
mroot(u);
access(v);
splay(u);
pre[v]=0;rt[v]=1;
ch[u][1]=0;up(u);
//up(x);
}
int main() {
//freopen("1.in","r",stdin);
//freopen("2.out","w",stdout);
int n,m,k;
n=read();
m=read();
k=read();
cnt=0;
tp=0;
inc(i,1,n) size[++cnt]=1,rt[cnt]=1;
int u,v,w;
while(m--) {
u=read();
v=read();
w=read();
size[++cnt]=1,rt[cnt]=1;
ke[cnt]=vul[cnt]=w;
Link(u,cnt);
Link(v,cnt);
}
char str[5];
while(k--) {
scanf("%s",str);
if(str[0]=='L') {
u=read(),v=read(),w=read(),size[++cnt]=1,rt[cnt]=1;
ke[cnt]=vul[cnt]=w;
Link(u,cnt),Link(v,cnt);
} else if(str[0]=='C') {
u=read();
v=read();
destory(u,v);
} else if(str[0]=='F') u=read(),mroot(u),key[u]^=1,up(u);
else u=read(),mroot(u),printf("%lld\n",sum[u]);
}
return 0;
}