(353) | xxx | 5 | 187 | +00:05 | +00:10 | +100:28 | +00:53 | +01:21 |
|
A:
倒着枚举就行,复杂度是够的,不要纯On^2就行。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define ls (o<<1)
#define rs (o<<1|1)
//#define m (l+r)/2
#define pb push_back
typedef pair<int,int> pii;
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
bool f=false;
int a=-1,b,c;
for(int i=0;i*7<=n;i++){
int tp=n-i*7;
if(f)break;
for(int j=0;j*5<=tp;j++){
int tp2=tp-=j*5;
if(tp2%3==0){
f=true;
a=i,b=j,c=tp2/3;
break;
}
}
}
if(a==-1)cout<<-1<<endl;
else cout<<c<<" "<<b<<" "<<a<<endl;
}
return 0;
}
B:
显然一次倒水后,最小值就变成了0,每次只需要倒次大的给最大的即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define ls (o<<1)
#define rs (o<<1|1)
//#define m (l+r)/2
#define pb push_back
typedef pair<int,int> pii;
const double PI= acos(-1.0);
const int M = 2e5+7;
/*
int head[M],cnt=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
ll ans=0;
sort(a+1,a+1+n);
if(k==0){
cout<<a[n]-a[1]<<endl;
continue;
}
ans=a[n];
for(int i=n-1;i>=n-k;i--){
ans+=a[i];
}
cout<<ans<<endl;
}
return 0;
}
C:
每次选择最右边两个数,最终得到的数一定是2,而结果不可能小于2,因为1与另一个不为1的数消去最小是2.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define ls (o<<1)
#define rs (o<<1|1)
//#define m (l+r)/2
#define pb push_back
typedef pair<int,int> pii;
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
ll sm=0;
sm=(1+n)*n/2;
cout<<2<<endl;
cout<<n-1<<" "<<n<<"\n";
for(int i=n-2;i>=1;i--)
cout<<i<<" "<<i+2<<"\n";
}
return 0;
}
D:
一个比较显然的贪心:
先把01串分段,连续相同的为一段。
从左往右处理每段,每次操作一肯定是先消去最前面且段长不为1的段,然后2操作把最前面的段消去。这样能保证2操作能做更多次,即结果最大!
然后找数组最左边不为1的数,并使它减一,用线段树即可处理。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define ls (o<<1)
#define rs (o<<1|1)
#define m (l+r)/2
#define pb push_back
typedef pair<int,int> pii;
const double PI= acos(-1.0);
const int M = 2e5+7;
/*
int head[M],cnt=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
char s[M];
int p[M],sz=0;
int tr[M<<2];
void bd(int o,int l,int r){
tr[o]=0;
if(l==r){
return ;
}
bd(ls,l,m);
bd(rs,m+1,r);
}
void up(int o,int l,int r,int x,int d){
if(l==r){
tr[o]+=d;
return ;
}
if(x<=m)up(ls,l,m,x,d);
else up(rs,m+1,r,x,d);
tr[o]=tr[ls]+tr[rs];
}
int qu(int o,int l,int r,int x,int y){//区间最左边不为1的数的位置
if(l==r)return l;
if(x<=m){
if(tr[ls]>m-l+1)return qu(ls,l,m,x,y);
}
if(y>m){
if(tr[rs]>r-m)return qu(rs,m+1,r,x,y);
}
return -1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
cin>>(s+1);
int nm=0;sz=0;
for(int i=1;i<=n;i++){
nm++;
if(s[i]!=s[i+1]){
p[++sz]=nm;
nm=0;
}
}bd(1,1,sz);
for(int i=1;i<=sz;i++)up(1,1,sz,i,p[i]);
//cout<<i<<" - "<<p[i]<<endl;;
int ans=0;
for(int i=1;i<=sz;i++){
int id=qu(1,1,sz,i,sz);
ans++;
if(id<i||p[id]==1){
if(i+1<=sz)up(1,1,sz,i+1,-p[i+1]+1);
i++;
}
else{
up(1,1,sz,id,-1);
p[id]--;
}
up(1,1,sz,i,-p[i]+1);//用过的都赋值为1
}
cout<<ans<<endl;
}
return 0;
}
E:
把一个串通过移动相邻串移动成其反转串。
看到相邻串移动就能先到逆序对。
显然对于一个串a。
移动到串b,一定是从左往右第i个'a',相对齐,然后跑个逆序对即可。
例如:
abac
caba
1234
4123 (反转串第一个字符'c' 在原串4位置上,第二个字符'a',是第一个'a',在原串1位置上,后面类似。。)
求4123逆序对个数即可。。
仔细想一下这里为什么成立,其实对逆序对足够熟练,这题就很裸了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define ls (o<<1)
#define rs (o<<1|1)
//#define m (l+r)/2
#define pb push_back
typedef pair<int,int> pii;
const double PI= acos(-1.0);
const int M = 4e5+7;
/*
int head[M],cnt=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int c[M];
int n;
void add(int x,int d){
while(x<=n){
c[x]+=d;
x+=x&(-x);
}
}
ll qu(int x){
ll ans=0;
while(x){
ans+=c[x];
x-=x&(-x);
}
return ans;
}
char s[M],p[M];
int nm[M],g[55];
vector<int> v[55];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>(s+1);
for(int i=1;i<=n;i++){
p[i]=s[n-i+1];
}
for(int i=1;i<=n;i++){
v[p[i]-'a'+1].pb(i);
}
for(int i=1;i<=n;i++){
int ch=s[i]-'a'+1;
nm[i]=v[ch][g[ch]];
++g[ch];
}
// cout<<"oko "<<endl;
ll ans=0;
for(int i=1;i<=n;i++){
// cout<<i<<" "<<t[i]<<endl;
add(nm[i],1);
ans+=qu(n);
ans-=qu(nm[i]);
// cout<<qu(n)
}
cout<<ans<<endl;
return 0;
}