B Element Swapping
如果(i,j)是答案,那么容易得到
两式子相除得到a[i]+a[j],然后针对右式是否为0的情况讨论一下,再根据第一个式子去判断一下。
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=100010;
int n,m,k;
ll sum[maxn],x,y,X,Y;
ll ans,ct,cnt,tmp,flag;
struct node
{
ll v,id;
bool operator<(node aa)const
{
return v<aa.v;
}
}a[maxn];
int ok[maxn];
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--){
scanf("%d%lld%lld",&n,&X,&Y);
x=X;y=Y;
rep(i,1,n)
{
ok[i]=0;
scanf("%lld",&a[i].v);
x-=(ll)i*a[i].v;
y-=(ll)i*a[i].v*a[i].v;
a[i].id=i;
}
sort(a+1,a+n+1);
ans=0;
if(x==0&&y) {puts("0");continue;}
if(x==0&&y==0)
{
int i=1;
ll tmp=0;
while(i<=n)
{
tmp=0;
int j=i;
while(j<=n&&a[j].v==a[i].v) {j++;tmp++;}
ans+=(tmp*(tmp-1))/2;
i=j;
}
printf("%lld\n",ans);
continue;
}
else if(y%x) {puts("0");continue;}
else {
int tim=1;
y=y/x;
int i=1,j=n;
while(i<j)
{
tim++;
int k=i;
ll tmp=0;
ll cnt=0;
while(k<j&&2LL*a[k].v==y&&a[k].v==a[i].v)
k++;
if(i!=k) {i=k;continue;}
tmp=0;
while(j>i&&a[j].v+a[i].v>y) j--;
if(j==i) break;
if(a[i].v+a[j].v!=y) {i++;continue;}
if(x%(a[j].v-a[i].v)!=0) {i++;continue;}
ll z=x/(a[j].v-a[i].v);
//cout<<x<<" "<<a[j].v-a[i].v<<" "<<z<<endl;
k=i;
while(k<j&&a[k].v==a[i].v) {
if((ll)a[k].id-z<=(ll)n&&(ll)a[k].id-z>0LL)
{
ok[a[k].id-(int)z]=tim;
//cout<<a[k].id<<" "<<z<<endl;
}
k++;
}
while(j>=k&&a[i].v+a[j].v==y) {
if(ok[a[j].id]==tim) ans++;
j--;
}
i=k;
}
}
printf("%lld\n",ans);
// if(flag) puts("Yes"); else puts("No");
}
return 0;
}
E Sequence in the Pocket
贪心,每次最大的能不动就不动,若值x动了,那么小于x的值一定都要按序提到前面去,所以一定是从最大值开始考虑,尽量不动,一个数只有在所有比它大的数的左面,这个数就可以不动,所以权值相同时,还要按下标排序。不过当遇到某数需要前移时,还需考虑,左面,权值相同,并且在所有比它大的数的左面的数不用移动。
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=100005;
int n,ans;
struct AA
{
int rt,x;
bool operator<(const AA&aa)const
{
if(x==aa.x) return rt<aa.rt;
return x<aa.x;
}
}pos[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&pos[i].x);
pos[i].rt=i;
}
sort(pos+1,pos+1+n);
int l=0,r=1;
for(int i=n-1;i>=1;i--)
{
if(pos[i].rt>pos[i+1].rt) {
for(int j=i-1;j>=1;j--)
{
if(pos[j].x!=pos[i].x)
{
r=j+1;break;
}
if(l==0&&pos[j].rt<pos[i+1].rt)
{
l=j;
}
}
ans=i;
if(l!=0)
{
ans-=l-r+1;
}
break;
}
}
printf("%d\n",ans);
}
return 0;
}
F Abbreviation
签到
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
const int inf=0x3f3f3f3f;
double pi=3.141592653589793238462643383279502884;
const ll mod=1e9+7;
const int maxn=300005;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char s[105];
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<len;i++)
{
if(i==0)
printf("%c",s[i]);
else
{
if(s[i]=='a'||s[i]=='e'||s[i]=='i'||s[i]=='y'||s[i]=='o'||s[i]=='u')
continue;
else
printf("%c",s[i]);
}
}
printf("\n");
}
return 0;
}
G Lucky 7 in the Pocket
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=200010;
int n,m,k;
int a[maxn],sum[maxn];
int c[maxn];
int ans,ct,cnt,tmp,flag;
char s[maxn];
int main()
{
int T,cas=1;
scanf("%d",&n);
{
ans=0; flag=1;
//memset(c,0,sizeof(c));
rep(i,1,n){
scanf("%d",&m);
while(1)
{
if(m%7==0&&m%4!=0) break;
m++;
}
printf("%d\n",m);
}
//printf("%d\n",ans);
// if(flag) puts("Yes"); else puts("No");
}
return 0;
}
H Singing Everywhere
预处理一个前缀和表示前i个音有多少个跑掉,然后暴力枚举删掉哪个就行。复杂度O(n)。
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=100010;
int n,m,k;
ll a[maxn],sum[maxn];
ll ans,ct,cnt,tmp,flag;
char s[maxn];
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
a[0]=a[n+1]=inf;
sum[0]=0;
rep(i,1,n) scanf("%lld",&a[i]);
if(n<3) {puts("0");continue;}
rep(i,1,n){
sum[i]=sum[i-1]+(a[i]>a[i-1]&&a[i]>a[i+1]);
}
ans=sum[n];
if(a[2]>a[1]&&a[2]>a[3])
ans=min(ans,sum[n]-1);
if(a[n-1]>a[n-2]&&a[n-1]>a[n])
ans=min(ans,sum[n]-1);
rep(i,2,n-1)
ans=min(ans,sum[n]-sum[i+1]+sum[i-2]+(a[i-1]>a[i-2]&&a[i-1]>a[i+1])+(a[i+1]>a[i-1]&&a[i+1]>a[i+2]));
printf("%lld\n",ans);
// if(flag) puts("Yes"); else puts("No");
}
return 0;
}
I Fibonacci in the Pocket
大数,很容易发现斐波那契数列的前缀和奇偶性为 奇奇偶 奇奇偶 奇奇偶 奇奇偶
所以只需要模3判断一下即可。
import java.math.*;
import java.util.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static BigInteger zero=new BigInteger("0");
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//result.toString();
int T,cas=1;
int n,m,cnt=0;
BigInteger tmp=new BigInteger("0");
BigInteger aa=new BigInteger("0");
BigInteger a=new BigInteger("0");
BigInteger b=new BigInteger("0");
BigInteger zero=new BigInteger("0");
BigInteger one=new BigInteger("1");
BigInteger two=new BigInteger("2");
BigInteger three=new BigInteger("3");
n=sc.nextInt();
while(n>0)
{
n--;
a=sc.nextBigInteger();
b=sc.nextBigInteger();
tmp=a.mod(three);
aa=b.mod(three);
if(tmp.equals(two)&&!aa.equals(one))
System.out.println(one);
else if(!tmp.equals(two)&&aa.equals(one))
System.out.println(one);
else System.out.println(zero);
}
}
}
J Welcome Party
并查集+优先队列,朋友关系是双向的,不开心的人的数量就是关系图的块数,每个块,需且只需一个人不开心,剩下的人都可以通过关系一个个进屋,不至于不开心,所以并查集判断关系分块,选定不开心的人为下标最小的,让其成为块内最早进屋的,由此决定字典序最小。
然后就用优先队列,每次选择可以进屋的人中编号最小的让其进屋,
首先将所有不高兴的人进队列,选出最小的编号的人,让其先进屋,然后将其朋友,加入队列(后面都是没有加入队列的加入过队列即可),在选最小的
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=1000005;
int pre[maxn],ans,t[maxn];
int find(int x)
{
int r=x;
if(x==pre[x]) return x;
else
return pre[x]=find(pre[x]);
}
void join(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
{
ans--;//cout<<x<<" ! "<<y<<endl;
if(fx<fy)
pre[fy]=fx;
else
{
pre[fx]=fy;
}
}
return;
}
struct AA
{
int v,next;
}pos[maxn*3];
int n,m,a,b,vis[maxn],f[maxn],num,k;
void add(int x,int y)
{
pos[++num].v=y;
pos[num].next=f[x];
f[x]=num;
pos[++num].v=x;
pos[num].next=f[y];
f[y]=num;
}
priority_queue<int,vector<int>, greater<int> >pq;
void dfs()
{
while(!pq.empty())
{
int x=pq.top();
k++;
if(k==n)
printf("%d\n",x);
else printf("%d ",x);
pq.pop();
for(int i=f[x];i!=-1;i=pos[i].next)
{
int v=pos[i].v;
if(vis[v]) continue;
else {vis[v]=1;pq.push(v);}
}
}
return;
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
while(!pq.empty()) pq.pop();
scanf("%d%d",&n,&m);
k=0;
ans=n;
for(int i=1;i<=n;i++)
{
pre[i]=i;
vis[i]=0;
f[i]=-1;
}
num=0;
while(m--)
{
scanf("%d%d",&a,&b);
add(a,b);
join(a,b);
}
printf("%d\n",ans);
for(int i=1;i<=n;i++)
{
if(vis[find(i)]==0)
{
vis[find(i)]=1;
pq.push(find(i));
}
else continue;
}
dfs();
// for(int i=1;i<n;i++)
// {
// printf("%d ",t[i]);
// }
// printf("%d\n",t[n]);
}
}
K Strings in the Pocket
这个题其实很水。。。如果S串和T相同,则答案为回文子串个数(想想是不是)
如果不同,则从开头找到第一个不同的位置l,从最后找到第一个不同的位置r,如果l~r翻转不相同,则答案为0,否则若S[l-1]==S[r+1],则答案++,l--,r++。
#include <bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
#define ll long long int
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
const int maxn=2000005;
char s[maxn],t[maxn];
int Len[maxn<<1],pos;
char tmp[maxn<<1];
int l,r;
ll ans;
int init(char *st)
{
int i,len=strlen(st);
tmp[0]='@';
for(i=1;i<=2*len;i+=2)
{
tmp[i]='#';
tmp[i+1]=st[i/2];
}
tmp[2*len+1]='#';
tmp[2*len+2]='$';
tmp[2*len+3]=0;
return 2*len+1;
}
void manacher(char *st,int len)
{
int mx=0,po=0;
for(int i=1;i<=len;i++)
{
if(mx>i)
Len[i]=min(mx-i,Len[2*po-i]);
else
Len[i]=1;
while(st[i-Len[i]]==st[i+Len[i]])
Len[i]++;
if(Len[i]+i>mx)
{
mx=Len[i]+i;
po=i;
}
l=(i-1)/2-(Len[i]-1)/2;
r=(i-1)/2+(Len[i]-1)/2;
if(Len[i]&1) r--;
//cout<<l<<" "<<r<<endl;
ans+=((r-l+2)/2);
}
printf("%lld\n",ans);
return ;
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
ans=0;
scanf("%s%s",s,t);
int n=strlen(s);
l=-1;
for(int i=0;i<n;i++)
{
if(s[i]!=t[i]) {l=i;break;}
}
if(l!=-1)
{
r=-1;
for(int i=n-1;i>=0;i--)
{
if(s[i]!=t[i]) {r=i;break;}
}
int j=r,ok=0;
for(int i=l;i<=r;i++,j--)
{
if(s[i]!=t[j])
{
ok=1;break;
}
}
if(ok)
{
printf("0\n");
}
else
{
ans=1;
for(int i=1;i<=l&&r+i<n;i++)
{
if(s[l-i]==s[r+i]) ans++;
else break;
}
printf("%lld\n",ans);
}
}
else///s==t的时候
{
int len=init(s);
manacher(tmp,len);
}
}
}