太菜了,心态炸了。QAQ
A-Vertices in the Pocket()
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4100
题目大意:给出T组合数据,每组数据n个点,m次询问,每次有两种情况,1.x,y之间链接一条边。2.如果这个图加入k条边,输出最少的联通块数和最多的联通快数。注意,连点的时候,一对点只能连一条边,即x y连后,不能再连x y了。
思路:看着像CF里面的一道题,当时猛哥读出来的时候说这个先放一放,最后写,结果最后也没有写。。。
最少的联通快个数很好求,当前联通快个数-k即可。(在不同的联通快之间连边),注意联通快的最小个数为1.
剩下就是求最大的联通块个数了。我们已经有一些联通块了,(操作1给出的联通快可以用并查集来维护)。同时用权值线段树维护联通快的大小,可用边的数量,联通快数量。
剩下的就是找最少链接几个联通快能把这k条边都用上。我们贪心的每次都选择最大的联通快,然后是次大的,再次的。。
选到最后,二分剩余的联通快的个数,取最小值即可。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
class WeiSegment{
ll SizDots[MAXN<<2],AvailableEdge[MAXN<<2],UnicomBlock[MAXN<<2];
//大小为k的块的点的个数,可容纳边总和,大小为k的块点的个数总和
//显然,初始化:
//SizDots:一开始大小为1的块的个数为n,
//AvailableEdge:可容纳边的总和为0,
//UnicomBlock:点1的个数总和为n
int n;
void PushUp(int rt){
SizDots[rt]=SizDots[rt<<1]+SizDots[rt<<1|1];
AvailableEdge[rt]=AvailableEdge[rt<<1]+AvailableEdge[rt<<1|1];
UnicomBlock[rt]=UnicomBlock[rt<<1]+UnicomBlock[rt<<1|1];
}
public :
void SetN(int Key){
n=Key;
}
void Build(int l,int r,int rt){
SizDots[rt]=AvailableEdge[rt]=UnicomBlock[rt]=0;
if(l==r){
if(l==1){
SizDots[rt]=UnicomBlock[rt]=n;
AvailableEdge[rt]=0;
}return ;
}
int mid=(l+r)>>1;
Build(l,mid,rt<<1);Build(mid+1,r,rt<<1|1);
// PushUp(rt);
}
void Update(int p,int l,int r,int rt){
if(l==r){
SizDots[rt]+=l;
AvailableEdge[rt]+=l*(l-1)/2;
UnicomBlock[rt]++;
return ;
}
int mid=(l+r)>>1;
if(p<=mid) Update(p,l,mid,rt<<1);
if(p>mid) Update(p,mid+1,r,rt<<1|1);
PushUp(rt);
}
void Del(int p,int l,int r,int rt){
if(l==r){
SizDots[rt]-=l;
AvailableEdge[rt]-=l*(l-1)/2;
UnicomBlock[rt]--;
return ;
}
int mid=(l+r)>>1;
if(p<=mid) Del(p,l,mid,rt<<1);
if(p>mid) Del(p,mid+1,r,rt<<1|1);
PushUp(rt);
}
int Query(ll k,ll v,int l,int r,int rt){
if(l==r){
int ql=1,qr=UnicomBlock[rt];
while(ql<=qr){
int mid=(ql+qr)>>1;
if((v+mid*l)*(v+mid*l-1)/2>=l*(l-1)/2*mid+k) qr=mid-1;
else ql=mid+1;
}return ql;
}
int mid=(l+r)>>1;
int Dots=SizDots[rt<<1|1],UsEdge=AvailableEdge[rt<<1|1];
if((v+Dots)*(v+Dots-1)/2>=k+UsEdge) return Query(k,v,mid+1,r,rt<<1|1);
else return Query(k+UsEdge,v+Dots,l,mid,rt<<1)+UnicomBlock[rt<<1|1];
}
};
WeiSegment WSeg;
int Pre[MAXN],Siz[MAXN];
int n,m;
void Intt(){
for(int i=0;i<=n;++i){
Pre[i]=i;Siz[i]=1;
}WSeg.SetN(n);WSeg.Build(1,n,1);
}
int Find(int x){
if(Pre[x]==x) return x;
return Pre[x]=Find(Pre[x]);
}
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);Intt();
ll AvailableEdge=0,UnicomBlock=n;
for(int i=1;i<=m;++i){
int oper;scanf("%d",&oper);
if(oper==1){
int x,y;scanf("%d%d",&x,&y);
int xx=Find(x),yy=Find(y);
if(xx!=yy){
WSeg.Del(Siz[xx],1,n,1);WSeg.Del(Siz[yy],1,n,1);
AvailableEdge-=Siz[xx]*(Siz[xx]-1)/2+Siz[yy]*(Siz[yy]-1)/2;
Siz[xx]=Siz[xx]+Siz[yy];Pre[yy]=xx;//联通
AvailableEdge+=Siz[xx]*(Siz[xx]-1)/2;
WSeg.Update(Siz[xx],1,n,1);
UnicomBlock--;
}AvailableEdge--;
}
else{
ll k;scanf("%lld",&k);
printf("%lld %lld\n",max(1ll,(UnicomBlock-k)),UnicomBlock+1-WSeg.Query(k-AvailableEdge,0,1,n,1));
}
}
}
}
B-Element Swapping()
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4101
看的我头疼,一脸蒙蔽,溜了溜了。
队友做的,题解:https://blog.csdn.net/henucm/article/details/89742028
D-Traveler
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6005
题目大意:一个人一开始在点1,要走到点n,其中每个点都要走一遍,问路径。行走的方式有四种:
1. i->i-1 2.i->2i 3.i->2i+1 4.i->int[i/2]
每个点只能走一次,每一步都不能超过n。
思路:试着写了几个点,画了波图,发现可以看成这样的:
直接一层一层的刷新就行了,跟本没有走不到的。具体看代码就好了
ACCOde:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
int Vis[MAXN];
int n;
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d",&n);
if(n==1){
printf("1\n");continue;
}
else if(n==2){
printf("1 2\n");continue;
}
else if(n==3){
printf("1 3 2\n");continue;
}
for(int i=0;i<=n;++i) Vis[i]=0;
printf("1");Vis[1]=1;
int x=2;
while(1){
if(Vis[x]==0){
printf(" %d",x);Vis[x]=1;
}
if(2*x==n){
printf(" %d",n);Vis[n]=1;
for(int i=n-1;Vis[i]==0;i-=2){
if(Vis[i]==0){
printf(" %d",i);Vis[i]=1;
}
if(Vis[i/2]==0){
printf(" %d",i/2);Vis[i/2]=1;
}
if(Vis[i-1]==0){
printf(" %d",i-1);Vis[i-1]=1;
}
}break;
}
else if(2*x+1==n){
for(int i=n;Vis[i]==0;i-=2){
if(Vis[i]==0){
printf(" %d",i);Vis[i]=1;
}
if(Vis[i/2]==0){
printf(" %d",i/2);Vis[i/2]=1;
}
if(Vis[i-1]==0){
printf(" %d",i-1);Vis[i-1]=1;
}
}break;
}
if(Vis[x-1]==0) x=x-1;
else x=x*2;
}printf("\n");
}
}
/*
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*/
E-Sequence in the Pocket
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4104
题目大意:n个数,每个数都可以放在一开始,给你一个排列,看最少经过多少次修改能使队列单调不减
思路:队友写的,我在摸鱼
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
int n;
struct node
{
int x,i;
}a[MAXN];
int mmp(node x,node y)
{
if(x.x!=y.x)
{
return x.x<y.x;
}
return x.i<y.i;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i].x);
a[i].i=i;
}
sort(a,a+n,mmp);
int f=1;
int i;
for(i=n-1;i>0;i--){
if(a[i].i>a[i-1].i){
f++;
}else
{
int j=i-1;
while(j>=0&&a[i-1].x==a[j].x){
if(a[j].i<a[i].i){
// printf("%d %d\n",a[j].x,a[i].x);
f++;
}
j--;
}
break;
}
}
printf("%d\n",n-f);
}
}
F-Abbreviation
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4105
题目大意:除了首字母外,其他定义为元音的字母都去掉。
思路:模拟就行了
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
char p[7]={'a','e','i','y','o','u'};
char s[MAXN];
int main(){
int T;//scanf("%d",&T);
while(~scanf("%d",&T)){
while(T--){
scanf("%s",&s);
int len=strlen(s);
printf("%c",s[0]);
for(int i=1;i<len;++i){
int flag=1;
for(int j=0;j<=5;++j){
if(s[i]==p[j]){
flag=0;break;
}
}
if(flag) printf("%c",s[i]);
}printf("\n");
}
}
}
G-Lucky 7 in the Pocket
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4106
题目大意:在n后面距离n最近的那个数,可以被7整除但不可以被4整除,输出。
思路:签到提,模拟。
ACCode:
int main(){
int T;scanf("%d",&T);
while(T--){
int n;scanf("%d",&n);
for(int i=n;1;++i){
if(i%7==0&&i%4!=0){
printf("%d\n",i);
break;
}
}
}
}
H-Singing Everywhere
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4107
题目大意:给出n个数,如果存在一个数a[i]>a[i-1]&&a[i]>a[i+1]那么就有一个“峰”,问最多删掉一个数,这个数组的最小峰的个数是多少?
思路:模拟,因为删掉一个数只会对前面和后面那个数产生影响,枚举模拟即可。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
int a[MAXN],b[MAXN];
int n;
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d",&n);
clean(b,0);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
}
int ans=0;
for(int i=2;i<n;++i){
if(a[i]>a[i-1]&&a[i]>a[i+1]){
b[i]=1;ans++;
}
}
int res=ans;
//特判2,n-1
int x=ans;
if(b[2]) x--;
if(a[3]>a[1]&&a[3]>a[4]){
if(b[3]) x=x;
else x++;
}
else{
if(b[3]) x--;
else x=x;
}res=min(res,x);
x=ans;
if(b[n-1]) x--;
if(a[n-1]>a[n-2]&&a[n-1]>a[n]){
if(b[n-1]) x=x;
else x++;
}
else{
if(b[n-1]) x--;
else x=x;
}res=min(res,x);
for(int i=3;i<=n-2;++i){
x=ans;
if(b[i]) x--;
if(a[i+1]>a[i-1]&&a[i+1]>a[i+2]){
if(b[i+1]) x=x;
else x++;
}
else{
if(b[i+1]) x--;
else x=x;
}
if(a[i-1]>a[i-2]&&a[i-1]>a[i+1]){
if(b[i-1]) x=x;
else x++;
}
else{
if(b[i-1]) x--;
else x=x;
}res=min(res,x);
}
printf("%d\n",res);
}
}
I-Fibonacci in the Pocket
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4108
题目大意:给你一个斐波那契数列,然后问你第x项加到第y项是奇数还是偶数,奇数输出1,偶数输出0.
思路:找到规律后发现三个一组都是奇奇偶,那么就可以%3直接判断了。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
char a[MAXN],b[MAXN];
int Sura(int len){
int ans=0;
for(int i=0;i<len;++i){
ans=ans*10+(a[i]-'0');
ans=ans%3;
}return ans;
}
int Surb(int len){
int ans=0;
for(int i=0;i<len;++i){
ans=ans*10+(b[i]-'0');
ans=ans%3;
}return ans;
}
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%s%s",&a,&b);
int lena=strlen(a),lenb=strlen(b);
int sura=Sura(lena),surb=Surb(lenb);
// cout<<"a: "<<sura<<" , "<<a<<endl;
// cout<<"b: "<<surb<<" , "<<b<<endl;
sura=(sura+3-1)%3;
// cout<<"sura,surb: "<<sura<<" "<<surb<<endl;
if(surb%2==0){
if(sura%2) printf("1\n");
else printf("0\n");
}
else{
if(sura%2) printf("0\n");
else printf("1\n");
}
}
}
J-Welcome Party()
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4109
题目大意:n个人,m个关系,然后让你找出n个人的进入房间的字典序最小的序列。房间里有不认识的人,进入后不开心。输出最小的不开心数。
思路:ZOJ栈啊!!!!!卡了我两个半小时,最后发现是爆栈了,改成BFS就过了!!换成数组模拟DFS也过了,佛了。
建好图之后,每个联通快编号最小的人先进去,优先队列来维护下一个进入的id。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e6+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
struct Node1{
int v,val,nxt;
Node1(int _v=0,int _val=0,int _nxt=0){
v=_v;val=_val;nxt=_nxt;
}
};
Node1 Edge[MAXN<<2];
int Head[MAXN];
//vector<int> Vec[MAXN];
int Belong[MAXN];
int Vis[MAXN];
int Ans[MAXN];
int n,m,Ecnt,Cnt;
priority_queue<int,vector<int>,greater<int> > que;
void Intt(){
for(int i=0;i<=n;++i){
Head[i]=-1;
Belong[i]=0;
Vis[i]=0;Ans[i]=0;
}Ecnt=0;Cnt=0;
}
void AddEdge(int u,int v,int val){
Edge[Ecnt]=Node1(v,val,Head[u]);
Head[u]=Ecnt++;
}
int Stk[MAXN],Top;
void DFS(int u){
Top=0;Stk[++Top]=u;
while(Top){
u=Stk[Top--];
if(Belong[u]==0){
Belong[u]=Cnt;
for(int i=Head[u];i+1;i=Edge[i].nxt){
int temp=Edge[i].v;
if(Belong[temp]==0){
Stk[++Top]=temp;
}
}
}
}
}
queue<int> que1;
void BFS(int u){
while(que1.size()) que1.pop();
que1.push(u);
while(que1.size()){
u=que1.front();que1.pop();
if(Belong[u]==0){
Belong[u]=Cnt;
for(int i=Head[u];i+1;i=Edge[i].nxt){
int temp=Edge[i].v;
if(Belong[temp]==0) que1.push(temp);
}
}
}
}
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);Intt();
for(int i=1;i<=m;++i){
int x,y;scanf("%d%d",&x,&y);
// Vec[x].push_back(y);Vec[y].push_back(x);
AddEdge(x,y,1);AddEdge(y,x,1);
}
for(int i=1;i<=n;++i){
if(Belong[i]==0){
++Cnt;
DFS(i);
//BFS(i);
}
}
for(int i=1;i<=n;++i){//Vis[i]是i联通快
if(Ans[Belong[i]]==0){//属于该种类的跟不存在
Ans[Belong[i]]=i;//赋予跟
}
}
for(int i=1;i<=Cnt;++i) que.push(Ans[i]);
printf("%d\n",Cnt);
// for(int i=1;i<=n;++i) cout<<i<<" : "<<Vis[i]<<endl;
int fir=1;
while(que.size()){
int u=que.top();que.pop();
// cout<<u<<" ";
if(Vis[u]) continue;
Vis[u]=1;
if(fir){
printf("%d",u);fir=0;
}
else printf(" %d",u);
for(int i=Head[u];i+1;i=Edge[i].nxt){
int temp=Edge[i].v;
if(Vis[temp]) continue;
que.push(temp);
}
// int len=Vec[u].size();
// for(int i=0;i<len;++i){
// int temp=Vec[u][i];
// if(Vis[temp]) continue;
// que.push(temp);
// }
}printf("\n");
}
}
/*
10
4 3
1 2
1 3
1 4
4 2
1 2
3 4
6 5
1 3
1 5
1 6
2 3
2 4
6 4
1 3
2 3
3 5
4 6
*/
K-Strings in the Pocket
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4110
文少写的,但是似乎还没发博客,于是我就先占个坑。据说是用马拉车写的。