2019HDU多校第一场

1002.Operation

传送:http://acm.hdu.edu.cn/showproblem.php?pid=6579

题意:给定一个长度为$n$的数列,$m$次操作,每次操作如下:

$0 l r$:查询区间$[l,r]$内若干个数的最大异或和。

$1 x$:给数列末尾添加一个数$x$。

数据范围:$1<=n,m<=5e5,1<=a_i<=2^{30}$。

分析:开始直接考虑用线段树维护区间线性基的并,然后每次查询求区间线性基,再求最大。(但是tle

贪心考虑答案。区间$[1,i]$的线性基一定是由$[1,i-1]$的线性基插入$a_i$后得到的。那么可以通过维护线性基的前缀和来得到答案。

(qaq,指路网友博客:https://blog.csdn.net/tyxacm/article/details/97156620

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=5e5+10;
 5 struct Linear_basis{
 6     ll b[maxn][35];int kk[maxn][35];
 7     void add(ll x,int id){
 8         int tot=id;
 9         for (int i=32;i>=0;i--){
10             b[tot][i]=b[tot-1][i];
11             kk[tot][i]=kk[tot-1][i];
12         }
13         for (int i=32;i>=0;i--){
14             if (x&(1ll<<i)){
15                 if (!b[tot][i]){
16                     b[tot][i]=x;
17                     kk[tot][i]=id;
18                     break;
19                 }
20                 else{
21                     if (id>kk[tot][i]){
22                         swap(b[tot][i],x);
23                         swap(kk[tot][i],id);
24                     }
25                     x^=b[tot][i];
26                 }
27             }
28         }
29     }
30     ll query(int l,int r){
31         ll res=0;
32         for (int i=32;i>=0;i--){
33             if (kk[r][i]>=l) res=max(res,res^b[r][i]);
34         }
35         return res;
36     }
37     void clear(int n){
38         for (int i=1;i<=n;i++) memset(b[i],0,sizeof(b[i])),memset(kk[i],0,sizeof(kk[i]));
39     }
40 }LB;
41 int main(){
42     int t,n,m,kk,l,r,x;scanf("%d",&t);
43     while (t--){
44         scanf("%d%d",&n,&m);
45         LB.clear(n);
46         for (int i=1;i<=n;i++){
47             scanf("%d",&x);
48             LB.add(x,i);
49         }
50         ll lastans=0;
51         while (m--){
52             scanf("%d",&kk);
53             if (kk==0){
54                 scanf("%d%d",&l,&r);
55                 l=(l^lastans)%n+1;
56                 r=(r^lastans)%n+1;
57                 if (l>r) swap(l,r);
58                 lastans=LB.query(l,r);
59                 printf("%lld\n",lastans);
60             }
61             else{
62                 scanf("%d",&x);
63                 x=x^lastans; n++;
64                 LB.add(x,n);
65             }
66         }
67     }
68     return 0;
69 } 
1002

1004.Vacation

传送:http://acm.hdu.edu.cn/showproblem.php?pid=6581

题意:一个路口,你前面有$n$辆车,给出每辆车的车长,距离路口的距离,以及每辆车的最大车速。要求这$n+1$辆车依此通过,问你的车头通过路口的时间花费了多少。

数据范围:$1<=n<=10^5,1<= s_i, v_i, l_i <=10^9$。

分析:

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int maxn=1e5+7;
 5 struct node{int l,s,v;ll len;} p[maxn];
 6 int main()
 7 {
 8     int n;
 9     while (~scanf("%d",&n))
10     {
11         for (int i=0;i<=n;i++) p[i].l=p[i].s=p[i].v=p[i].len=0;
12         for (int i=0;i<=n;i++) scanf("%d",&p[i].l);
13         for (int i=0;i<=n;i++) scanf("%d",&p[i].s);
14         for (int i=0;i<=n;i++) scanf("%d",&p[i].v);
15         for (int i=1;i<=n;i++) p[i].len+=p[i-1].len+1ll*p[i].l;
16         for (int i=1;i<=n;i++) p[i].len+=1ll*p[i].s;
17         p[0].len=p[0].s;
18         double ans=0.0;
19         for (int i=0;i<=n;i++) ans=max(ans,1.0*p[i].len/(1.0*p[i].v));
20         printf("%.10f\n",ans);
21     }
22     return 0;
23 }
1004

1005.Path

传送:http://acm.hdu.edu.cn/showproblem.php?pid=6582

题意:有$n$点,$m$条路,要求切断一些路,使得从$1-n$的路比最短路大的最小花费。切断每一条路的花费就是每一条路的长度。

数据范围:$1<=n,m<=10^5,1<=c<=10^9$。

分析:题目要求就是要去掉一些路,使得最短路不成立。跑最短路选取出所有的最短路的边,然后用这些边跑最小割即可。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #define en '\n'
  7 #define low(x) (x)&(-x)
  8 #define m(a,b) memset(a,b,sizeof a)
  9 using namespace std;
 10 typedef long long ll;
 11 const int N=2e4+10,M=N;
 12 const ll INF=1e18;
 13 struct Edge{int to;ll len;int nex;}e[M],edge[M<<1];
 14 struct node{int x,y;ll c;}p[M];
 15 int head[N],tot,head2[N],ttt,n,m;
 16 void add(int from,int to,ll len)
 17 {
 18     edge[++tot]=(Edge){to,len,head[from]};head[from]=tot;
 19     edge[++tot]=(Edge){from,0,head[to]};head[to]=tot;
 20 }
 21 void add_edge(int from,int to,ll len){
 22     e[++ttt]=(Edge){to,len,head2[from]};head2[from]=ttt;
 23 }
 24 priority_queue<pair<ll,int>>Q;
 25 ll d[N],da[N],db[N];
 26 void dijkstra(int s)
 27 {
 28     for (int i=0;i<=n;i++) d[i]=INF;
 29     d[s]=0;Q.push(make_pair(0,s));
 30     while(!Q.empty())
 31     {
 32         int x=Q.top().second;Q.pop();
 33         for(int i=head2[x];i;i=e[i].nex)
 34         {
 35             int y=e[i].to;ll z=e[i].len;
 36             if(d[y]>d[x]+z)
 37             {
 38                 d[y]=d[x]+z;
 39                 Q.push(make_pair(-d[y],y));
 40             }
 41         }
 42     }
 43 }
 44 int s,t;
 45 queue<int>q;
 46 bool bfs()
 47 {
 48     for (int i=0;i<=n;i++) d[i]=0;
 49     while(!q.empty())q.pop();
 50     q.push(s);d[s]=1;
 51     while(!q.empty())
 52     {
 53         int x=q.front();q.pop();
 54         for(int i=head[x];i;i=edge[i].nex)
 55         {
 56             int y=edge[i].to;ll l=edge[i].len;
 57             if(!d[y]&&l)
 58             {
 59                 q.push(y),d[y]=d[x]+1;
 60                 if(y==t) return 1;
 61             }
 62         }
 63     }
 64     return 0;
 65 }
 66 ll dinic(int x,ll flow)
 67 {
 68     if(x==t) return flow;
 69     ll res=flow,k;
 70     for(int i=head[x];i&&res;i=edge[i].nex)
 71     {
 72         int y=edge[i].to;ll l=edge[i].len;
 73         if(l&&d[y]==d[x]+1)
 74         {
 75             k=dinic(y,min(res,l));
 76             if(!k){d[y]=0;continue;}
 77             edge[i].len-=k,edge[i^1].len+=k,res-=k;
 78         }
 79     }
 80     return flow-res;
 81 }
 82 int main()
 83 {
 84     int T;scanf("%d",&T);
 85     while(T--)
 86     {
 87         scanf("%d%d",&n,&m);
 88         for (int i=0;i<=n;i++) head[i]=0,head2[i]=0;
 89         ttt=0;tot=1;
 90         for(int i=1;i<=m;++i)
 91         {
 92             scanf("%d%d%lld",&p[i].x,&p[i].y,&p[i].c);
 93             add_edge(p[i].x,p[i].y,p[i].c);
 94         }
 95         dijkstra(1);
 96         if(d[n]==INF) {puts("0");continue;}
 97         for (int i=0;i<=n;i++) da[i]=d[i],head2[i]=0;
 98         ttt=0;
 99         for(int i=1;i<=m;++i) add_edge(p[i].y,p[i].x,p[i].c);
100         dijkstra(n);
101         for (int i=1;i<=n;i++) db[i]=d[i];
102         for(int i=1;i<=m;++i)
103         {
104             if(da[p[i].x]+db[p[i].y]+p[i].c==da[n])
105                 add(p[i].x,p[i].y,p[i].c);
106         }
107         for (int i=0;i<=n;i++) d[i]=0;
108         s=1,t=n;
109         ll maxflow=0;
110         while(bfs()) maxflow+=dinic(s,INF);
111         printf("%lld\n",maxflow);
112     }
113 }
1005

 

转载于:https://www.cnblogs.com/changer-qyz/p/11233672.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值