Assign the task

来源:互联网 发布:千县万村农村淘宝计划 编辑:程序博客网 时间:2024/05/18 11:49
There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the leader of whole company).If you are the immediate boss of someone,that person is your subordinate, and all his subordinates are your subordinates as well. If you are nobody's boss, then you have no subordinates,the employee who has no immediate boss is the leader of whole company.So it means the N employees form a tree.

The company usually assigns some tasks to some employees to finish.When a task is assigned to someone,He/She will assigned it to all his/her subordinates.In other words,the person and all his/her subordinates received a task in the same time. Furthermore,whenever a employee received a task,he/she will stop the current task(if he/she has) and start the new one.

Write a program that will help in figuring out some employee’s current task after the company assign some tasks to some employee.

Input
The first line contains a single positive integer T( T <= 10 ), indicates the number of test cases.

For each test case:

The first line contains an integer N (N ≤ 50,000) , which is the number of the employees.

The following N - 1 lines each contain two integers u and v, which means the employee v is the immediate boss of employee u(1<=u,v<=N).

The next line contains an integer M (M ≤ 50,000).

The following M lines each contain a message which is either

"C x" which means an inquiry for the current task of employee x

or

"T x y"which means the company assign task y to employee x.

(1<=x<=N,0<=y<=10^9)
Output
For each test case, print the test case number (beginning with 1) in the first line and then for every inquiry, output the correspond answer per line.
Sample Input
1 5 4 3 3 2 1 3 5 2 5 C 3 T 2 1 C 3 T 3 2 C 3
Sample Output
Case #1:-1 1 2

一。并查集(没有路径压缩)

#include <iostream>#include<stdio.h>#include<string.h>#include<algorithm>#define INF 0x3f3f3f3f#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define mid_line(x,y) ((x+y)>>1)using namespace std;typedef long long ll;const int maxn=5e4+10;int pre[maxn];int ans[maxn];int t[maxn];//记录更新的时间,这样的话,才是最后一次的int find_root(int x){    int r=x;    int ed=x;    int time=t[x];    while(pre[r]!=r)    {        if(t[pre[r]]>=time)//不应该只是父亲大于儿子,应该是这条路线上最大的那个时间        {            time=t[pre[r]];            ed=pre[r];        }        r=pre[r];    }    return ed;}void query(int x){    printf("%d\n",ans[find_root(x)]);}void ass(int x,int y){    ans[x]=y;}int main(){  int T;  int cnt=1;  scanf("%d",&T);  while(T--)  {      memset(t,0,sizeof(t));      memset(pre,0,sizeof(pre));      memset(ans,-1,sizeof(ans));      int n;      scanf("%d",&n);      for(int i=0;i<=n;i++)        pre[i]=i;      for(int i=1;i<n;i++)      {          int son,father;          scanf("%d %d",&son,&father);          pre[son]=father;      }      printf("Case #%d:\n",cnt++);      int m;      scanf("%d",&m);      for(int i=1;i<=m;i++)      {          char ch;int x,y;          scanf(" %c",&ch);          if(ch=='C')          {              scanf("%d",&x);              query(x);          }          else          {              scanf("%d %d",&x,&y);              t[x]=i;              ass(x,y);          }      }  }   return 0;}
二。线段树

#include <iostream>#include<stdio.h>#include<vector>#include<string.h>#include<algorithm>#define INF 0x3f3f3f3f#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define mid_line(x,y) ((x+y)>>1)#define lowbit(x) (x&(-x))using namespace std;typedef long long ll;/*这道题用线段树来做,感觉真的很别扭,这句话是真的,之前都是一维数组,我们给数组填充数值,这样的话,树就建好了。可是这道题不是一维的,不能直接填充。我们还是先建立好一棵树,每个节点的st和ed,还是不变的,只是我们更新的时候去找合适的区间罢了。我们得先给他们来编号,也就是利用深搜,看看每个值的左右区间。比如2[1,5],这就是他的区间,所以更新的时候,我们只需要在线段树里面找到这个区间,然后修改了他们就好了。还有一点,就是我们发现他都是从根上下来,所以我们必须把之前的操作执行完了,我们再去执行现在的操作,lazy的价值*/const int maxn=5e4+10;int n;int vis[maxn];//看看谁是主子,或者说谁没有当过儿子vector<int> graph[maxn];//存储连接关系int start[maxn],End[maxn];int id;//编号struct node{    int l,r;    int lazy,tag;}tree[maxn*4];void dfs(int x)//这一步是在分配编号,也就是说每个人所掌管的范围我们已经给变换出来了{    id++;    start[x]=id;//每个点的开始都是自己    for(int i=0;i<graph[x].size();i++)        dfs(graph[x][i]);    End[x]=id;}void build(int st,int ed,int nid){    tree[nid].l=st;    tree[nid].r=ed;    tree[nid].tag=-1;    tree[nid].lazy=0;    if(st==ed) return;    int mid=mid_line(st,ed);    build(st,mid,lson(nid));    build(mid+1,ed,rson(nid));}void update(int nid,int st,int ed,int mis){    if(tree[nid].l==st&&tree[nid].r==ed)//到达指定区间,开始懒惰标记    {        tree[nid].lazy=1;        tree[nid].tag=mis;        return;//好几次忘记了写这个return    }    int mid=mid_line(tree[nid].l,tree[nid].r);    if(tree[nid].lazy)//释放标记,就像是先把之前的抹上,再抹上现在,最后显现的就是最后抹上的    {        update(lson(nid),tree[nid].l,mid,tree[nid].tag);        update(rson(nid),mid+1,tree[nid].r,tree[nid].tag);        tree[nid].lazy=0;//只记得释放,没有把标记清除    }    if(ed<=mid)        update(lson(nid),st,ed,mis);    else if(st>mid)        update(rson(nid),st,ed,mis);    else        update(lson(nid),st,mid,mis),update(rson(nid),mid+1,ed,mis);}int query(int nid,int num)//查询的时候也是踹一步,lazy,标记走一步,{    if(tree[nid].l==tree[nid].r)        return tree[nid].tag;    int mid=mid_line(tree[nid].l,tree[nid].r);    if(tree[nid].lazy)//释放标记,也就是把以前的先抹一遍    {        update(lson(nid),tree[nid].l,mid,tree[nid].tag);        update(rson(nid),mid+1,tree[nid].r,tree[nid].tag);    }    if(num<=mid)        return query(lson(nid),num);    else        return query(rson(nid),num);}int main(){  int T,cnt=1;  scanf("%d",&T);  while(T--)  {    id=0;    for(int i=0;i<=n;i++)        graph[i].clear();    memset(vis,0,sizeof(vis));    scanf("%d",&n);    for(int i=1;i<n;i++)    {        int u,v;        scanf("%d %d",&v,&u);        graph[u].push_back(v);        vis[v]=1;//说明他有主人    }    for(int i=1;i<=n;i++)        if(!vis[i])//找到boss,开始进行编号        {          dfs(i);break;        }    build(1,n,1);    printf("Case #%d:\n",cnt++);    int m_ch;    scanf("%d",&m_ch);    while(m_ch--)    {        int u,mis;char op;        scanf(" %c",&op);        if(op=='C')        {            scanf("%d",&u);            printf("%d\n",query(1,start[u]));//我们事先标记了u的起始位置,这也正是他的树中的编号        }        else        {            scanf("%d %d",&u,&mis);            update(1,start[u],End[u],mis);        }    }  }  return 0;}


原创粉丝点击