这次从D题开始写,40min写完D刚想提交就没电了,换舍友电脑安装devC又写了一遍,然后忘开longlong fst了。。。
D题:水题,对每个点二分出所能贡献的最远的那个点,预处理完后,直接无脑树剖。
晕死。。。哪需要什么树链剖分,直接利用数组维护前缀和的方法在树上dfs一下就好了。。。
#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;
int n;
struct Node{
int v,w;
};
vector<Node> G[maxn];
ll Dep[maxn];
int p[maxn];
int stk[maxn],stkn;
int u,v,w;
int dep[maxn],son[maxn],fa[maxn],siz[maxn];
int top[maxn];
int id[maxn];
int num;
int tr[maxn<<2];
int a[maxn];
void dfs1(int u,int f,int d){
fa[u]=f;
dep[u]=d;
son[u]=0;
siz[u]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i].v;
if(v==f) continue;
dfs1(v,u,d+1);
if(siz[v]>siz[son[u]]) son[u]=v;
siz[u]+=siz[v];
}
}
void dfs2(int u,int tp){
top[u]=tp;
id[u]=++num;
if(son[u]) dfs2(son[u],tp);
for(int i=0;i<G[u].size();i++){
int v=G[u][i].v;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
void build(int l,int r,int rt){
if(l==r){
tr[rt]=0;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
tr[rt]+=c;
return;
}
int m=(l+r)>>1;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
}
int query(int p,int l,int r,int rt){
int res=0;
res+=tr[rt];
if(l==r) return res;
int m=(l+r)>>1;
if(p<=m) res+=query(p,lson);
else res+=query(p,rson);
return res;
}
int ask(int u){
return query(id[u],1,n,1);
}
void change(int u,int v,int c){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
update(id[top[u]],id[u],c,1,num,1);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
update(id[u],id[v],c,1,num,1);
}
void getDep(int u,int f,ll d){
Dep[u]=d;
for(int i=0;i<G[u].size();i++){
int v=G[u][i].v;ll w=G[u][i].w;
if(v==f) continue;
getDep(v,u,d+w);
}
}
int bin(int l,int r,int u){
int res=-1;
while(l<=r){
int m=(l+r)>>1;
int v=stk[m];
if(Dep[u]-Dep[v]<=a[u]) res=v,r=m-1;
else l=m+1;
}
return res;
}
void dfs(int u,int f){
p[u]=bin(1,stkn,u);
stk[++stkn]=u;
for(int i=0;i<G[u].size();i++){
int v=G[u][i].v;ll w=G[u][i].w;
if(v==f) continue;
dfs(v,u);
}
--stkn;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while(cin>>n){
for(int i=1;i<=n;i++) scanf("%d",&a[i]),G[i].clear();
for(int u=2;u<=n;u++){
scanf("%d%d",&v,&w);
G[u].push_back((Node){v,w});
G[v].push_back((Node){u,w});
}
num=0;
dfs1(1,0,1);
dfs2(1,1);
build(1,num,1);
getDep(1,0,0);
stkn=0;
dfs(1,0);
for(int i=2;i<=n;i++)
if(~p[i]) change(fa[i],p[i],1);
for(int i=1;i<=n;i++) printf("%d ",ask(i));puts("");
}
return 0;
}
C题:水题。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;
int n,m;
int l,r;
int main(){
while(cin>>n>>m){
int len=n+1;
for(int i=1;i<=m;i++) scanf("%d%d",&l,&r),len=min(len,r-l+1);
int now=0;
cout<<len<<endl;
for(int i=1;i<=n;i++){
printf("%d ",now);
now=(now+1)%len;
}
puts("");
}
return 0;
}
E题:水题。。。直接线段树维护就好了,合并的时候查询一下左右端点的值。。。一开始查询左右端点的值无脑加了个log,复杂度n*logn*logn,果断T了,然后发现只要把左右端点值放到线段树直接维护就好了,复杂度n*logn 。
#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;
int n,q;
int L,R,c;
struct Node{
ll add,lv,rv;
int ld,rd,lu,ru;
int Max;
};Node seg[maxn<<2];
void down(int rt){
if(seg[rt].add){
seg[rt<<1].add+=seg[rt].add;
seg[rt<<1|1].add+=seg[rt].add;
seg[rt<<1].lv+=seg[rt].add;
seg[rt<<1|1].rv+=seg[rt].add;
seg[rt<<1].rv+=seg[rt].add;
seg[rt<<1|1].lv+=seg[rt].add;
seg[rt].add=0;
}
}
void up(int rt,int l,int r,int m){
seg[rt].lv=seg[rt<<1].lv;
seg[rt].rv=seg[rt<<1|1].rv;
seg[rt].Max=max(seg[rt<<1].Max,seg[rt<<1|1].Max);
seg[rt].ld=seg[rt<<1].ld;
seg[rt].lu=seg[rt<<1].lu;
seg[rt].rd=seg[rt<<1|1].rd;
seg[rt].ru=seg[rt<<1|1].ru;
ll a=seg[rt<<1].rv,b=seg[rt<<1|1].lv;
if(a==b) return;
if(a<b){
seg[rt].Max=max(seg[rt].Max,seg[rt<<1].rd+seg[rt<<1|1].lu);
if(seg[rt<<1].rd==m-l+1) seg[rt].lu+=seg[rt<<1|1].lu;
if(seg[rt<<1|1].lu==r-m){
seg[rt].ru+=seg[rt<<1].rd;
if(seg[rt].rd==r-m) seg[rt].rd+=seg[rt<<1].rd;
}
}
if(a>b){
seg[rt].Max=max(seg[rt].Max,seg[rt<<1].ru+seg[rt<<1|1].ld);
if(seg[rt<<1].ru==m-l+1){
seg[rt].lu+=seg[rt<<1|1].ld;
if(seg[rt].ld==m-l+1) seg[rt].ld+=seg[rt<<1|1].ld;
}
if(seg[rt<<1|1].ld==r-m) seg[rt].ru+=seg[rt<<1].ru;
}
}
void build(int l,int r,int rt){
seg[rt].add=0;
if(l==r){
scanf("%d",&c);
seg[rt].lv=seg[rt].rv=c;
seg[rt].ld=seg[rt].rd=seg[rt].lu=seg[rt].ru=seg[rt].Max=1;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
up(rt,l,r,m);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
seg[rt].add+=c;
seg[rt].lv+=c;
seg[rt].rv+=c;
return;
}
int m=(l+r)>>1;
down(rt);
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
up(rt,l,r,m);
}
int main(){
freopen("in.txt","r",stdin);
while(~scanf("%d",&n)){
build(1,n,1);
scanf("%d",&q);
while(q--){
scanf("%d%d%d",&L,&R,&c);
update(L,R,c,1,n,1);
printf("%d\n",seg[1].Max);
}
}
return 0;
}