Productive Meeting
题意:n个人参加会议,每个人可以和别人交谈ai次,问会议最多有多少次交流
思路:贪心,每次用剩余交谈次数最大和次大的减一。
提醒我要去复习重载运算符了
#include <bits/stdc++.h>
#define MOD 1000000007;
#define freopen freopen("in.txt","r",stdin);
#define debug cout<<1<<endl;
#define fastio ios::sync_with_stdio(false);cout.tie(false);cin.tie(false);
#define vi vector <int>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define ll long long
using namespace std;
struct node
{
int x,y;
};
inline bool operator < (node a,node b)
{
return a.x<b.x;
}
int main()
{
//freopen
int t,n,x;
node p,temp1,temp2;
for(cin>>t;t;t--)
{
cin>>n;
priority_queue<node> q;
vi a,b;
ll ans=0;
for(int i=1;i<=n;i++)
{
cin>>x;
if(x==0)
continue;
p.x=x,p.y=i;
q.push(p);
}
while(q.size()>=2)
{
temp1=q.top();
q.pop();
temp2=q.top();
q.pop();
temp1.x--;
temp2.x--;
ans++;
a.push_back(temp1.y);b.push_back(temp2.y);
if(temp1.x>0)
q.push(temp1);
if(temp2.x>0)
q.push(temp2);
}
cout<<ans<<endl;
for(int i=0;i<(int)a.size();i++)
{
cout<<a[i]<<" "<<b[i]<<endl;
}
}
return 0;
}
学过离散的图论的话这题应该超级轻松,没学过自己画两个图也能做出来
#include <bits/stdc++.h>
#define MOD 1000000007;
#define freopen freopen("in.txt","r",stdin);
#define debug cout<<1<<endl;
#define fastio ios::sync_with_stdio(false);cout.tie(false);cin.tie(false);
#define vi vector <int>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define ll long long
using namespace std;
int main()
{
int t;
scanf("%d",&t);
for(register int i=0;i!=t;i++)
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
if((n-1ll)*n>>1<m||m<n-1)
{
NO
continue;
}
if(n==1){
if(k>1){
YES
}else{
NO
}
}else if(m<(n-1ll)*n>>1){
if(k>3){
YES
}else{
NO
}
}else if(k>2){
YES
}else{
NO
}
}
return 0;
}
给你个字符串,你可以删除其中的一种,注意是一种字母。
问:如果删除这种字母就能让字符串变回文串,那么删去那种字母删除字母的个数最少
注:如果咋删都不行,那就输出-1
思路:暴力遍历+贪心(这也能算贪心吗,,,)
对于每个字母删去的情况都遍历一下,取个最小值,复杂度也就26*n,1e6的复杂度肯定不超时。再我也想不出别的方法了
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
for(cin>>t;t;t--)
{
string s;
int n;
int min1=1000000000;
cin>>n>>s;
for(char a='a';a<='z';a++)
{
int con=0;
bool falg=true;
for(int i=0,j=n-1;i<j;)
{
if(s[i]==s[j])
{
i++;
j--;
continue;
}
else
{
if(s[i]==a)
{
i++;
con++;
}
else if(s[j]==a)
{
con++;
j--;
}
else
{
falg=false;
break;
}
}
}
if(falg)
{
min1=min(min1,con);
}
}
if(min1!=1000000000)
{
cout<<min1<<endl;
}
else
cout<<-1<<endl;
}
}
其实还有很多高效的写法,自己想去吧,,
Array Walk
题意可以自己点进去看
傻了吧,B题就是个DP,还是中等的那种。
这个DP属于一维上的DP,如果要是题目是这样说:我们可以向左走或者向右走,那么就很容易了,可以直接朴素的写一个dp一维的代表第x步向的最大值
但是这个题加上了最多向左走z步
所以设计dp[i][j]为花费i次向左走的机会后站在j的位置上最大获得多少分数
#include <bits/stdc++.h>
#define MOD 1000000007;
#define freopen freopen("in.txt","r",stdin);
#define debug cout<<1<<endl;
#define fastio ios::sync_with_stdio(false);cout.tie(false);cin.tie(false);
#define vi vector <int>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define ll long long
#define rint register int
using namespace std;
int a[200000+10],dp[6][200000+10];
int main()
{
int t,n,k,z;
//freopen
for(cin>>t;t;t--)
{
cin>>n>>k>>z;
int maxx=-1;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=0;i<=z;i++)
{
for(int j=1;j<=n;j++)
{
dp[i][j]=dp[i][j-1]+a[j];
if(i&&j!=n)
dp[i][j]=max(dp[i][j],dp[i-1][j+1]+a[j]);
if(i*2+j-1==k)
maxx=max(maxx,dp[i][j]);
}
}
cout<<maxx<<endl;
}
return 0;
}
这是一道纯纯模拟题,看完题意之后看代码就行了,,洛谷上的题解多少有些复杂,,我们还是普通模拟一下吧
#include <bits/stdc++.h>
using namespace std;
const int M = 2000010;
int t, n, a[69], b[69], f[M];
int main()
{
cin >> t;
while (t--)
{
cin >> n;
for (int i = 0; i < n; ++i)
cin >> a[i];
for (int mod = M; mod >= 1; --mod)
{
int best = 0;
for (int i = 0; i < n; ++i)
{
b[i] = a[i] % mod;
if (b[i] < 0)
b[i] += mod;
++f[b[i]], best = max(best, f[b[i]]);
}
for (int i = 0; i < n; ++i)
--f[b[i]];
if (best >= n / 2)
{
if (mod == M)
mod = -1;
cout << mod << '\n';
break;
}
}
}
return 0;
}
atcoder的思维题,不涉及算法,是个有意思的思维构造题。
我们能在观察中发现
1.如果分组的话,那么二元数的和相同的就是一个组
2.每个组中,二元数的第二个数代表的就是其这个组中是第几个二元数
#include <bits/stdc++.h>
#define MOD 1000000007;
#define freopen freopen("in.txt","r",stdin);
#define debug cout<<1<<endl;
#define fastio ios::sync_with_stdio(false);cout.tie(false);cin.tie(false);
#define vi vector <int>
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define ll long long
#define rint register int
using namespace std;
int first,second;
void get(int n)
{
int sum=2,x=1;
while(n>1)
{
x++;
if(sum<=x)
{
sum++;
x=1;
}
n--;
}
first=sum-x;
second=x;
}
int main()
{
int a,b;
cin>>a>>b;
get(a);
int f1=first,s1=second;
get(b);
int f2=first,s2=second;
first=0;second=s1+s2;
for(int i=1;i<=f1+f2+s1+s2-2;i++)
first+=i;
cout<<first+second<<endl;
return 0;
}
明天开篇来一个并查集的逻辑推理题。