题目问两点间的路径上子路径权的第k小,一开始给出能做子路径的路径p[]和其权值
有一篇介绍的很详细的题解
http://www.cnblogs.com/mjy0724/p/4447813.html
看了思路知道怎么做会打的下面我写的东西都可以不看了
窝讲一下个人具体的做法(不会具体怎么做的可以看下)
这道题整体二分就是二分一个路径的权值,将当前考虑的矩阵按是否在二分的范围内分类拿出来,像归并排序那样把这个区间的矩阵编号重新排一下(这样往下二分时可以直接带编号区间下去)
然后扫描线扫一遍,求出每个点被多少个矩阵包含了,如果超出k那就把它扔到左边二分,否则扔到右边且k减去询问的答案(点也像矩阵那样重新排一遍),二分时就带二分区间、矩阵编号区间,点编号区间下去
窝不会区间修改的树状数组…打了线段树,每次二分线段树注意不能暴力清空不然复杂度就退化了,会T,询问到哪里清空到哪里(还有种做法是每次撤销掉之前的操作)
#include
#include
#include
#include
#include
#include
using namespace std;
void read(int &x)
{
char c;
while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9')(x*=10)+=c-'0';
}
const int maxn = 81000;
const int maxd = 18;
struct edge{int y,next;}a[maxn];int len,fir[maxn];
void insert(int x,int y){len++;a[len].y=y;a[len].next=fir[x];fir[x]=len;}
struct plate
{
int l,r,h,s,flag;
}p[maxn<<2],b[maxn<<2],br[maxn<<2]; int num;
struct node
{
int x,y,id,k,ans;
}point[maxn],c[maxn],cr[maxn];
int dep[maxn],fa[maxn][maxd],dfn[maxn],nex[maxn],id;
int s[maxn],tree[maxn<<2];
int times[maxn<<2];
int n,m,Q,ts;
void dfs(int x)
{
dfn[x]=++id;
for(int i=1;i<=maxd;i++)
{
if((1<dep[x])break;
fa[x][i]=fa[fa[x][i-1]][i-1];
}
for(int k=fir[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa[x][0])
{
fa[y][0]=x;
dep[y]=dep[x]+1;
dfs(y);
}
}
nex[x]=id;
}
int LCAson(int x,int y)
{
if(dep[x]y]){int t=x;x=y;y=t;}
for(int i=maxd-1;dep[x]!=dep[y]&&i>=0;i--)
if(fa[x][i]&&dep[fa[x][i]]>dep[y])x=fa[x][i];
if(fa[x][0]==y)return x;
x=fa[x][0];
for(int i=maxd-1;i>=0;i--)
if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}
return x;
}
void update(int x,int l,int r,int lx,int rx,int c)
{
if(times[x]!=ts){tree[x]=0;times[x]=ts;}
if(lx<=l&&r<=rx){tree[x]+=c;return ;}
int mid=(l+r)>>1,lc=x<<1,rc=lc|1;
if(rx<=mid)update(lc,l,mid,lx,rx,c);
else if(lx>mid)update(rc,mid+1,r,lx,rx,c);
else update(lc,l,mid,lx,mid,c),update(rc,mid+1,r,mid+1,rx,c);
}
int Query(int x,int l,int r,int loc)
{
if(times[x]!=ts){tree[x]=0;times[x]=ts;}
if(l==r)return tree[x];
int ret=tree[x];
int mid=(l+r)>>1,lc=x<<1,rc=lc|1;
if(loc<=mid)return ret+Query(lc,l,mid,loc);
else return ret+Query(rc,mid+1,r,loc);
}
void solve(int l,int r,int lp,int rp,int pl,int pr)
{
if(pl>pr)return ;
if(l==r)
{
for(int i=pl;i<=pr;i++) point[i].ans=s[l];
return;
}
ts++;
int mid=(l+r)>>1,midx=s[mid];
int bn=0,brn=0,cn=0,crn=0;
for(int i=lp;i<=rp;i++)
{
if(p[i].s<=midx) b[++bn]=p[i];
else br[++brn]=p[i];
}
for(int i=1;i<=bn;i++) p[i+lp-1]=b[i];
for(int i=1;i<=brn;i++) p[lp+bn-1+i]=br[i];
int pos=pl;
for(int i=1;i<=bn;i++)
{
while(pos<=pr&&point[pos].yint temp=Query(1,1,id,point[pos].x);
if(temp>=point[pos].k) c[++cn]=point[pos];
else
{
cr[++crn]=point[pos];
cr[crn].k-=temp;
}
pos++;
}
update(1,1,id,b[i].l,b[i].r,b[i].flag);
}
while(pos<=pr)
{
int temp=Query(1,1,id,point[pos].x);
if(temp>=point[pos].k) c[++cn]=point[pos];
else
{
cr[++crn]=point[pos];
cr[crn].k-=temp;
}
pos++;
}
for(int i=1;i<=cn;i++)point[pl+i-1]=c[i];
for(int i=1;i<=crn;i++)point[pl+cn-1+i]=cr[i];
solve(l,mid,lp,lp+bn-1,pl,pl+cn-1);
solve(mid+1,r,lp+bn,rp,pl+cn,pr);
}
bool cmph(plate x,plate y){return x.h<y.h;}
bool cmp1(node x,node y){return x.y<y.y;}
bool cmp2(node x,node y){return x.id<y.id;}
int main()
{
len=id=0;memset(fir,0,sizeof fir);
read(n);read(m);read(Q);
for(int i=1;iint x,y;read(x);read(y);
insert(x,y);insert(y,x);
}
dfs(1);
num=0;
for(int i=1;i<=m;i++)
{
int x,y;read(x);read(y);read(s[i]);
if(dep[x]y]){int t=x;x=y;y=t;}
int la=LCAson(x,y),fla=fa[la][0];
if(fla==y)
{
num++;
p[num].s=s[i];p[num].l=1;p[num].r=dfn[la]-1;
p[num].h=dfn[x];p[num].flag=1;
num++;
p[num].s=s[i];p[num].l=1;p[num].r=dfn[la]-1;
p[num].h=nex[x]+1;p[num].flag=-1;
num++;
p[num].s=s[i];p[num].l=dfn[x];p[num].r=nex[x];
p[num].h=nex[la]+1;p[num].flag=1;
/*num++;
p[num].s=s[i];p[num].l=dfn[x];p[num].r=nex[x];
p[num].h=id+1;p[num].flag=-1;*/
}
else
{
if(dfn[x]>dfn[y]){int t=x;x=y;y=t;}
num++;
p[num].s=s[i];p[num].l=dfn[x];p[num].r=nex[x];
p[num].h=dfn[y];p[num].flag=1;
num++;
p[num].s=s[i];p[num].l=dfn[x];p[num].r=nex[x];
p[num].h=nex[y]+1;p[num].flag=-1;
}
}
sort(s+1,s+m+1);
sort(p+1,p+num+1,cmph);
for(int i=1;i<=Q;i++)
{
int x,y,k;read(x);read(y);read(k);
if(dfn[x]>dfn[y]){int t=x;x=y;y=t;}
point[i].x=dfn[x];point[i].y=dfn[y];
point[i].id=i;point[i].k=k;
}
sort(point+1,point+Q+1,cmp1);
ts=0; solve(1,m,1,num,1,Q);
sort(point+1,point+Q+1,cmp2);
for(int i=1;i<=Q;i++)printf("%d\n",point[i].ans);
return 0;
}