http://bbs.cnttr.com/?fromuid=478248

``` #include <bits/stdc++.h> #define ll long long #define lb(x) x&(-x) using namespace std; const ll N=1e5,M=5e5,TR=2e7; struct node{ ll ls,rs,w,val; }tr[TR+5]; ll n,m; ll a[N+5]; vector<ll> v[M+5]; ll b[M+5],cntb; ll root[M+5],cnttr; ll trr[N+5]; ll minn; void modify(ll x,ll y){ if(!x) return; for(ll i=x;i<=n;i+=lb(i)){ trr[i]+=y; } return; } ll query(ll x){ ll s=0; for(ll i=x;i;i-=lb(i)){ s+=trr[i]; } return s; } ll query(ll l,ll r){ return query(r)-query(l-1); } void split(ll p,ll v,ll &x,ll &y){ if(!p){ x=y=0; return; } if(tr[p].val<=v){ x=p; split(tr[p].rs,v,tr[p].rs,y); } else{ y=p; split(tr[p].ls,v,x,tr[p].ls); } return; } void merge(ll x,ll y,ll &p){ if(!x || !y){ p=x+y; return; } if(tr[x].w>=tr[y].w){ p=x; merge(tr[p].rs,y,tr[p].rs); } else{ p=y; merge(x,tr[p].ls,tr[p].ls); } return; } void build(ll &p,ll l,ll r){ if(l>r) return; ll mid=(l+r)>>1; p=++cnttr; tr[p]=(node){0,0,rand(),b[mid]}; build(tr[cnttr].ls,l,mid-1); build(tr[cnttr].rs,mid+1,r); return; } void dfs(ll p,ll x){ if(!p) return; minn=min(minn,p); dfs(tr[p].ls,x); ll pos=tr[p].val; modify(pos,-a[pos]+a[pos]/x); a[pos]/=x; if(a[pos]%x==0) b[++cntb]=pos; dfs(tr[p].rs,x); return; } void work(ll p){ if(!p) return; work(tr[p].ls); cout<<p<<" "<<tr[p].ls<<" "<<tr[p].rs<<" "<<tr[p].val<<endl; work(tr[p].rs); return; } int main(){ srand(time(NULL)); // srand(5); scanf("%lld%lld",&n,&m); for(ll i=1;i<=n;i++){ scanf("%lld",&a[i]); for(ll j=1;j*j<=a[i];j++){ if(i%j==0){ v[j].push_back(i); if(j*j!=a[i]) v[i/j].push_back(i); } } modify(i,a[i]); } for(ll i=1;i<=N;i++){ cntb=0; // cout<<i<<"ooooooo\n"; for(ll j:v[i]){ b[++cntb]=j; // cout<<j<<" "; } // cout<<endl; build(root[i],1,cntb); } while(m--){ ll op,l,r,v; scanf("%lld%lld%lld",&op,&l,&r); if(op==1){ scanf("%lld",&v); if(v<=1) continue; ll x=0,y=0,z=0; split(root[v],r,x,z); split(x,l-1,x,y); // work(y); minn=TR; cntb=0; dfs(y,v); // cnttr=minn-1; build(y,1,cntb); merge(x,y,x); merge(x,z,root[v]); } else printf("%lld\n",query(l,r)); } return 0; } /* 5 1 1 2 3 4 5 1 1 5 2 */ ``` # P3987 我永远喜欢珂朵莉~ ## 题目背景 http://sukasuka-anime.com/ 戒不掉的珂毒 出不动的分块 ![](https://cdn.luogu.com.cn/upload/pic/11191.png) ![](https://cdn.luogu.com.cn/upload/pic/11192.png) ![](https://cdn.luogu.com.cn/upload/pic/11193.png) 哦对了有没有想买BD的珂学家啊?支持一下墨鱼吧~ 或者有没有人想来手办众筹啊? ## 题目描述 给珂朵莉一个长为 $n$ 的非负数序列 $a$,支持以下两个操作: - $\verb!1 l r x!$:把区间 $[l,r]$ 中所有 $x$ 的倍数除以 $x$。 - $\verb!2 l r!$:查询区间 $[l,r]$ 内元素的和。 珂朵莉很可爱,所以你要帮珂朵莉写这个题。 ## 输入格式 第一行两个数表示 $n,m$。 第二行 $n$ 个非负整数表示 $a_i$。 之后 $m$ 行每行一个操作: - $\verb!1 l r x!$:把区间 $[l,r]$ 中所有 $x$ 的倍数除以 $x$。 - $\verb!2 l r!$:查询区间 $[l,r]$ 内元素的和。 ## 输出格式 对于每次询问,输出一行一个数表示答案。 ## 输入输出样例 #1 ### 输入 #1 ``` 5 3 1 2 3 4 5 2 1 5 1 1 5 2 2 1 5 ``` ### 输出 #1 ``` 15 12 ``` ## 说明/提示 ### 数据范围及约定 $1 \le n , m \le 10^5$,$0 \le a_i \le 5\times 10^5$,$1 \le x \le 5\times 10^5$。 上面代码过不了样例
08-14
``` #include <bits/stdc++.h> #define ll long long #define lb(x) x&(-x) using namespace std; const ll N=1e5,M=5e5,TR=2e7; struct node{ ll ls,rs,w,val; }tr[TR+5]; ll n,m; ll a[N+5]; vector<ll> v[M+5]; ll b[M+5],cntb; ll root[M+5],cnttr; ll trr[N+5]; void modify(ll x,ll y){ if(!x) return; for(ll i=x;i<=n;i+=lb(i)){ trr[i]+=y; } return; } ll query(ll x){ ll s=0; for(ll i=x;i;i-=lb(i)){ s+=trr[i]; } return s; } ll query(ll l,ll r){ return query(r)-query(l-1); } void split(ll p,ll v,ll &x,ll &y){ if(!p){ x=y=0; return; } if(tr[p].val<=v){ x=p; split(tr[p].rs,v,tr[p].rs,y); } else{ y=p; split(tr[p].ls,v,x,tr[p].ls); } return; } void merge(ll x,ll y,ll &p){ if(!x || !y){ p=x+y; return; } if(tr[x].w>=tr[y].w){ p=x; merge(tr[p].rs,y,tr[p].rs); } else{ p=y; merge(x,tr[p].ls,tr[p].ls); } return; } void build(ll &p,ll l,ll r){ if(l>r) return; ll mid=(l+r)>>1; p=++cnttr; tr[p]=(node){0,0,rand(),b[mid]}; build(tr[cnttr].ls,l,mid-1); build(tr[cnttr].rs,mid+1,r); return; } void dfs(ll p,ll x){ if(!p) return; dfs(tr[p].ls,x); ll pos=tr[p].val; if(a[pos]%x==0){ modify(pos,-a[pos]+a[pos]/x); a[pos]/=x; } if(a[pos]%x==0) b[++cntb]=pos; dfs(tr[p].rs,x); return; } void work(ll p){ if(!p) return; work(tr[p].ls); cout<<p<<" "<<tr[p].ls<<" "<<tr[p].rs<<" "<<tr[p].val<<endl; work(tr[p].rs); return; } int main(){ srand(time(NULL)); // srand(5); scanf("%lld%lld",&n,&m); for(ll i=1;i<=n;i++){ scanf("%lld",&a[i]); for(ll j=1;j*j<=a[i];j++){ if(a[i]%j==0){ v[j].push_back(i); if(j*j!=a[i]) v[a[i]/j].push_back(i); } } modify(i,a[i]); } for(ll i=1;i<=M;i++){ cntb=0; // cout<<i<<"ooooooo\n"; for(ll j:v[i]){ b[++cntb]=j; // cout<<j<<" "; } // cout<<endl; build(root[i],1,cntb); } while(m--){ ll op,l,r,v; scanf("%lld%lld%lld",&op,&l,&r); if(op==1){ scanf("%lld",&v); if(v<=1) continue; ll x=0,y=0,z=0; split(root[v],r,x,z); split(x,l-1,x,y); // work(y); cntb=0; dfs(y,v); build(y,1,cntb); merge(x,y,x); merge(x,z,root[v]); } else printf("%lld\n",query(l,r)); } return 0; } /* 5 1 1 2 3 4 5 1 1 5 2 */ ``` 问题已修复,仍然答案错误
08-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值