题目大意:在1~m中选n个不同的数 要求和为X/Y 求方案数
爆搜的话应该是100E左右 所以考虑加剪枝
上下界剪枝 如果当前的情况下剩余的数最大都无法到达目标或最小都无法小于目标 则剪枝
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 200200 using namespace std; struct Segtree{ Segtree *ls,*rs; int num; void* operator new (size_t size,Segtree *_,Segtree *__,int ___); }*tree[M],*mempool,*C; struct edge{ int x,y,f; bool operator < (const edge &Y) const { return f < Y.f ; } }edges[500500]; struct abcd{ int to,next; }table[M]; int head[M],tot; int n,m,q,ans; int a[M],fa[M][20],dis[M][20],belong[M]; int seq[M],l[M],r[M],cnt; void* Segtree :: operator new (size_t size,Segtree *_,Segtree *__,int ___) { if(C==mempool) { C=new Segtree[1<<15]; mempool=C+(1<<15); } C->ls=_; C->rs=__; C->num=___; return C++; } void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } int Find(int x) { if(!belong[x]||belong[x]==x) return belong[x]=x; return belong[x]=Find(belong[x]); } void Kruskal() { int i; sort(edges+1,edges+m+1); for(i=1;i<=m;i++) { int x=Find(edges[i].x); int y=Find(edges[i].y); if(x==y) continue; belong[x]=belong[y]=++n; fa[x][0]=fa[y][0]=n; dis[x][0]=dis[y][0]=edges[i].f; Add(n,x);Add(n,y); printf("%d %d\n",n,x); printf("%d %d\n",n,y); printf("%d[label=\"%d\",fontcolor=red]\n",n,edges[i].f); } } void DFS(int x) { int i; seq[l[x]=++cnt]=a[x]; for(i=head[x];i;i=table[i].next) DFS(table[i].to); r[x]=cnt; } Segtree* Build_Tree(Segtree *p,int x,int y,int val) { int mid=x+y>>1; if(x==y) return new (0x0,0x0,p->num+1) Segtree; if(val<=mid) return new (Build_Tree(p->ls,x,mid,val),p->rs,p->num+1) Segtree; else return new (p->ls,Build_Tree(p->rs,mid+1,y,val),p->num+1) Segtree; } int Get_Kth(Segtree *p1,Segtree *p2,int x,int y,int k) { int mid=x+y>>1; if(x==y) return mid; int temp=p2->rs->num-p1->rs->num; if(k<=temp) return Get_Kth(p1->rs,p2->rs,mid+1,y,k); else return Get_Kth(p1->ls,p2->ls,x,mid,k-temp); } int Get_Root(int x,int y) { int j; for(j=19;~j;j--) if( fa[x][j] && dis[x][j]<=y ) x=fa[x][j]; return x; } int main() { int i,j,v,x,k; cin>>n>>m>>q; for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=m;i++) scanf("%d%d%d",&edges[i].x,&edges[i].y,&edges[i].f); Kruskal(); for(j=1;j<=19;j++) for(i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1], dis[i][j]=max(dis[i][j-1],dis[fa[i][j-1]][j-1]); DFS(n); tree[0]=new (0x0,0x0,0) Segtree; tree[0]->ls=tree[0]->rs=tree[0]; for(i=1;i<=n;i++) tree[i]=Build_Tree(tree[i-1],0,1000000000,seq[i]); for(i=1;i<=q;i++) { scanf("%d%d%d",&v,&x,&k); //x^=ans;v^=ans;k^=ans; int root=Get_Root(v,x); if(r[root]-l[root]+1<k) { puts("-1"); ans=0; continue; } ans=Get_Kth(tree[l[root]-1],tree[r[root]],0,1000000000,k); if(!ans) { puts("-1"); continue; } printf("%d\n",ans); } }
时间: 2024-10-12 10:41:51