T1
An idea of this problem is that we first put all the points into the heap, then take out the weight and the smallest group from the heap each time, and then insert a point that can be inserted into the group each time. However, the number of elements put into the heap cannot be estimated and will be jammed. There are several optimizations below:
- First, we change the heap to multiset, and then if the sum of the number of elements taken and the number of elements in the set is greater than \ (k \), we can delete the largest ones. Another optimization is that if the current element is greater than \ (k \) and the current insertion value is greater than the maximum value, we will not insert.
- We first sort the weights of all points, and then we take out one group at a time. There are two operations. The first is to remove the largest point and replace it with a larger point. Or we can add the smallest point in the group.
- Let's change our thinking, consider the value of dichotomy, and then consider whether we can find \ (k \) clusters so that the weights of these clusters are less than the value of dichotomy. We consider expanding from an empty set and adding a point that can be added each time. We need to ensure that the added weight is smaller than the dichotomy value, otherwise stop expanding. In this way, we will expand \ (k \) times at most, and then we can use it__ int128 to press which points can be added to the current group.
The code uses the first implementation method.
code:
#include<iostream> #include<bits/stdc++.h> #include<cstdio> #include<algorithm> #include<bitset> #include<queue> #define ll long long #define N 110 using namespace std; bitset<110> v[N]; template<typename T> inline void read(T &x){ x=0;int flag=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') flag*=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; x*=flag; } struct Node{ ll val; bitset<110> bit; inline Node(){} inline bool operator < (const Node &b)const{ return val<b.val; } }; multiset<Node> S; int n,k,a[N],cnt; char s[N]; inline void Init(){ read(n);read(k);k--; for(int i=1;i<=n;i++) read(a[i]); for(int i=1;i<=n;i++){ scanf("%s",s+1); for(int j=1;j<=n;j++){ v[i][j]=s[j]-'0'; } } for(int i=1;i<=n;i++){ Node now;now.bit.reset(); now.bit[i]=1;now.val=a[i]; S.insert(now); } } int main(){ // freopen("my.in","r",stdin); // freopen("my.out","w",stdout); Init(); while(S.size()){ Node Top=(*S.begin());S.erase(S.begin()); cnt++; if(cnt==k){ printf("%lld",Top.val);return 0; } int posi=-1; for(int i=1;i<=n;i++) if(Top.bit[i]) posi=i+1; while(S.size()+cnt>k) S.erase(--S.end()); for(int j=posi;j<=n;j++){ if((v[j]&Top.bit)==Top.bit&&(!(S.size()+cnt>k&&Top.val+a[j]>=(*(--S.end())).val))){ Top.bit[j]=1;Top.val+=a[j]; S.insert(Top); Top.bit[j]=0;Top.val-=a[j]; } } } puts("-1"); return 0; }
T2
We first consider that \ (a_i \) must be a value in \ (b_,b_,b_i \), because we only need a relative size. We can always adjust this value to become a value in \ (B \), of course, when there is a solution. So we have three values for each position. Let \ (f_ \) mean that the number of \ (I \) is placed in the value of \ (I \), and the number of \ (j \) is placed in the value of \ (k \). Whether there is a solution, transfer it. Code implementation skills.
code:
#include<bits/stdc++.h> #define dd double #define ld long double #define ll long long #define uint unsigned int #define ull unsigned long long #define N 100010 #define M number using namespace std; const int INF=0x3f3f3f3f; template<typename T> inline void read(T &x) { x=0; int f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c == '-') f=-f; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; x*=f; } inline int GetMid(int a,int b,int c){ if(a>b) swap(a,b);if(b>c) swap(b,c);if(a>b) swap(a,b); return b; } int b[N],t,n,a[N][3],Pre[N][3][3],ans[N]; bool f[N][3][3]; inline void Clear(){ for(int i=1;i<=n;i++){ for(int j=0;j<=2;j++) for(int k=0;k<=2;k++){ f[i][j][k]=0;Pre[i][j][k]=-1; } } } inline void Init(){ read(n); for(int i=3;i<=n;i++) read(b[i]); b[1]=b[2]=b[3]; b[n+1]=b[n+2]=b[n]; for(int i=1;i<=n;i++){ a[i][0]=b[i];a[i][1]=b[i+1];a[i][2]=b[i+2]; // printf("a[%d][0]=%d a[%d][1]=%d a[2][%d]=%d\n",i,a[i][0],i,a[i][1],i,a[i][2]); } for(int i=1;i<=2;i++) for(int j=0;j<=2;j++) for(int k=0;k<=2;k++) f[i][j][k]=1; } inline void Solve(){ for(int i=3;i<=n;i++) for(int j=0;j<=2;j++) for(int k=0;k<=2;k++){ if(!f[i-1][k][j]) continue; for(int l=0;l<=2;l++){ if(GetMid(a[i][l],a[i-1][k],a[i-2][j])!=b[i]) continue; f[i][l][k]=1;Pre[i][l][k]=j; // printf("f[%d][%d][%d]=%d\n",i-1,k,j,f[i-1][k][j]); // printf("f[%d][%d][%d]=%d\n",i,l,k,f[i][l][k]); // printf("Pre[%d][%d][%d]=%d\n",i,l,k,Pre[i][l][k]); } } int nowj=-1,nowk=-1; for(int j=0;j<=2;j++) for(int k=0;k<=2;k++) if(f[n][j][k]) // printf("nowj=%d nowk=%d\n",nowj,nowk); if(nowj==-1&&nowk==-1) return(void)puts("-1"); int now=n; while(nowj!=-1&&nowk!=-1){ ans[now]=a[now][nowj]; // printf("a[%d][%d]=%d\n",now,nowj,a[now][nowj]); int Next=Pre[now][nowj][nowk];nowj=nowk;nowk=Next;now--; // printf("Next=%d\n",Next); if(Next==-1){ ans[now]=a[now][nowk];break; } } ans[1]=b[1]; for(int i=1;i<=n;i++) printf("%d ",ans[i]);puts(""); } int main(){ // freopen("my.in","r",stdin); // freopen("my.out","w",stdout); memset(f,0,sizeof(f));memset(Pre,-1,sizeof(Pre)); read(t); while(t--){ Init();Solve();Clear(); } return 0; }
T3 and T4 are not NOIP content, so they will not be supplemented for the time being.