2021.10.17

T1:裂变链接

Problem:

现在有𝑁个异构体在前线排成一排参与战斗,但由于地方火力过于凶猛,异构体们都受到了不同程度的损伤。为了能够让所有异构体继续战斗,避免由于能量不均衡导致的爆炸,异构体们需要使得他们彼此之间的能量值一样。记第𝑖个异构体当前𝑒𝑖的能量,每个时刻,每个异构体都可以做如下三种操作中的一种:
1、传递1的能量给自己左边相邻的异构体(如果存在)。
2、传递1的能量给自己右边相邻的异构体(如果存在)。
3、传递1的能量给自己(摸鱼)。
为了尽快的回到前线作战,异构体们希望在最短的时间内使得所有异构体的能量值一样,问最短时间。数据保证有解。操作过程中自己的能量可以变为负数。

Solution:

每个物体只用考虑能量向左还是向右传递,找到需要传递能量最多的物体即可。

Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=100010;
 4 int n,z[maxn];
 5 long long sum[maxn];
 6 void read(){
 7     scanf("%d",&n);
 8     for(int a=1;a<=n;a++) scanf("%d",&z[a]);
 9 }
10 long long work(){
11     for(int a=1;a<=n;a++) sum[a]=sum[a-1]+z[a];
12     if(sum[n]%n) return -1;
13     long long ans=0,v=sum[n]/n;
14     for(int a=1;a<=n;a++){
15         long long l=sum[a-1]-1ll*(a-1)*v;
16         long long r=sum[n]-sum[a]-1ll*(n-a)*v;
17         if(l<0&&r<0) ans=max(ans,-l-r);
18         ans=max(ans,max(abs(l),abs(r)));
19     }
20     return ans;
21 }
22 int main(){
23     read();
24     printf("%lld\n",work());
25     return 0;
26 }

T2:死亡鸽者

Problem:

死亡鸽者最喜欢的事情就是咕咕咕,他的座右铭“风萧萧兮易水寒,壮士一去兮不复返,然鸽子至今未到”也每天被他所忘记。今天,死亡鸽者又要开始咕咕的旅行了。现在有𝑁座城市排成一排,死亡鸽者会从第一座城市一直走到最后一座城市。每个城市都有一个数𝑎𝑖,每次死亡鸽者可以选择取走或者不取走这个数,但想要取走这个数的话要求这个数必须是所有已经取走的数的倍数或者约数。现在问死亡鸽者从第一座城市走到最后一座城市的过程中,最多取走多少个数。

Solution:

所有数的顺序并不影响,按照所有数从小到大排序后可以转化为取倍数问题。利用类似于埃式筛法的思路可以做到O(nlogn)。

Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1000010;
 4 int n,cnt[maxn],f[maxn];
 5 int main(){
 6     scanf("%d",&n);
 7     for(int a=1;a<=n;a++){
 8         int v;
 9         scanf("%d",&v);
10         cnt[v]++;
11         f[v]++;
12     }
13     int ans=0;
14     for(int a=1;a<=1000000;a++){
15         if(f[a]){
16             if(f[a]>ans) ans=f[a];
17             for(int b=a+a;b<=1000000;b+=a){
18                 if(cnt[b]&&f[a]+cnt[b]>f[b]) f[b]=f[a]+cnt[b];
19             }
20         }
21     }
22     printf("%d\n",ans);
23     return 0;
24 }

T3:进阶之灾

Problem:

TarjanLusa 是一款风靡全球的卡牌游戏,在这款游戏中,你需要一层一层的前进,击败像萌死戳、天启骑士等 boss,最终来到心脏面前一决胜负。为了能够有一套更好的卡牌来面对心脏,我们需要在每一层选择更好的卡牌。假设我们总共有𝑁层,在第𝑖层的时候,我们可以从两张卡牌中选择一张加入我们的卡组,这两张卡牌的战斗力分别为𝑎𝑖, 𝑏𝑖。在经过𝑁层的选择之后,我们便会有一套𝑁张卡的卡组,而整套卡组的战斗力取决于卡牌与卡牌之间战斗力差值的绝对值的最小值。但是心脏是一个非常强大的敌人,如果我们不能拥有强大的战斗力,人类就
会一败涂地。所以,现在我们想知道,战斗力最大可能是多少。

Solution:

二分答案。
每次检验的时候会发现,一组卡牌中的一张选了会导致其他某组卡牌必须选另外一张,从而转化为2-SAT问题。
但由于数据范围过大,直接2SAT无法建图,注意到所有的边都是在一个区间里面的边,所以用线段树优化建图即可。

Code:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=200010;
  4 const int maxp=maxn+(maxn<<2);
  5 const int maxm=maxn+maxp+maxn*40;
  6 int n,size,cnt,en,t,dfn[maxp],low[maxp],s[maxp],belong[maxp],pos[maxn];
  7 bool instack[maxp];
  8 struct edge{
  9     int e;
 10     edge *next;
 11 }*v[maxp],ed[maxm];
 12 void add_edge(int s,int e){
 13     en++;
 14     ed[en].next=v[s];
 15     v[s]=ed+en;
 16     v[s]->e=e;
 17 }
 18 struct rec{
 19     int v,p;
 20     rec(){}
 21     rec(int a,int b){
 22         v=a;
 23         p=b;
 24     }
 25 }z[maxn];
 26 bool operator<(const rec &a,const rec &b){
 27     return a.v<b.v;
 28 }
 29 void dfs(int p){
 30     t++;
 31     dfn[p]=low[p]=t;
 32     instack[p]=true;
 33     s[++size]=p;
 34     for(edge *e=v[p];e;e=e->next){
 35         if(!dfn[e->e]){
 36             dfs(e->e);
 37             low[p]=min(low[p],low[e->e]);
 38         }
 39         else{
 40             if(instack[e->e]) low[p]=min(low[p],dfn[e->e]);
 41         }
 42     }
 43     if(dfn[p]==low[p]){
 44         cnt++;
 45         while(s[size]!=p){
 46             belong[s[size]]=cnt;
 47             instack[s[size]]=false;
 48             size--;
 49         }
 50         belong[p]=cnt;
 51         instack[p]=false;
 52         size--;
 53     }
 54 }
 55 void build(int l,int r,int rt){
 56     if(l==r){
 57         add_edge(rt+(n<<1),z[l].p<=n?z[l].p+n:z[l].p-n);
 58         return;
 59     }
 60     int m=(l+r)>>1;
 61     build(l,m,rt<<1);
 62     build(m+1,r,rt<<1|1);
 63     add_edge(rt+(n<<1),(rt<<1)+(n<<1));
 64     add_edge(rt+(n<<1),(rt<<1|1)+(n<<1));
 65 }
 66 void insert(int l,int r,int rt,int nowl,int nowr,int p){
 67     if(nowl<=l&&r<=nowr){
 68         add_edge(p,rt+(n<<1));
 69         return;
 70     }
 71     int m=(l+r)>>1;
 72     if(nowl<=m) insert(l,m,rt<<1,nowl,nowr,p);
 73     if(m<nowr) insert(m+1,r,rt<<1|1,nowl,nowr,p);
 74 }
 75 bool check(int k){
 76     en=0;
 77     cnt=0;
 78     memset(v,0,sizeof(v));
 79     memset(dfn,0,sizeof(dfn));
 80     build(1,(n<<1),1);
 81     int r=1,l=1;
 82     for(int a=1;a<=(n<<1);a++){
 83         int op,p=z[a].p;
 84         if(p<=n) op=pos[p+n];
 85         else op=pos[p-n];
 86         while(r<=a&&z[r].v<=z[a].v-k) r++;
 87         if(r<a&&r>=1&&z[r].v>z[a].v-k){
 88             if(op>=r&&op<=a-1){
 89                 if(op>r) insert(1,(n<<1),1,r,op-1,z[a].p);
 90                 if(op<a-1) insert(1,(n<<1),1,op+1,a-1,z[a].p);
 91             }
 92             else insert(1,(n<<1),1,r,a-1,z[a].p);
 93         }
 94         while(l<=(n<<1)&&z[l].v<z[a].v+k) l++;
 95         l--;
 96         if(l>a&&l<=(n<<1)&&z[l].v<z[a].v+k){
 97             if(op>=a+1&&op<=l){
 98                 if(op>a+1) insert(1,(n<<1),1,a+1,op-1,z[a].p);
 99                 if(op<l) insert(1,(n<<1),1,op+1,l,z[a].p);
100             }
101             else insert(1,(n<<1),1,a+1,l,z[a].p);
102         }
103     }
104     for(int a=1;a<=(n<<1);a++) if(!dfn[a]) dfs(a);
105     for(int a=1;a<=n;a++) if(belong[a]==belong[a+n]) return false;
106     return true;
107 }
108 int main(){
109     scanf("%d",&n);
110     int minv=0x3f3f3f3f,maxv=-0x3f3f3f3f;
111     int x=0;
112     for(int a=1;a<=n;a++){
113         int v1,v2;
114         scanf("%d%d",&v1,&v2);
115         z[++x]=rec(v1,a);
116         z[++x]=rec(v2,a+n);
117         minv=min(minv,min(v1,v2));
118         maxv=max(maxv,max(v1,v2));
119     }
120     if(maxv-minv+1<n){
121         printf("0\n");
122         return 0;
123     }
124     sort(z+1,z+x+1);
125     for(int a=1;a<=(n<<1);a++) pos[z[a].p]=a;
126     int l=0,r=1000000001;
127     while(l+1!=r){
128         int m=(l+r)>>1;
129         if(check(m)) l=m;
130         else r=m;
131     }
132     printf("%d\n",l);
133     return 0;
134 }
posted @ 2021-10-17 20:26  B_lank  阅读(72)  评论(0编辑  收藏  举报