Camp
文章目录
day1
输入n,输出n行n列的由+
和.
组成的正方形,其中最外面一圈全是+
,第二圈全是.
,…,对于第ii圈,如果ii是奇数,那么全是+
,否则全是.
void solve(){
int n,x;
cin>>n;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
int minn=n;
x=i;
minn=min(x,minn);
x=n+1-i;
minn=min(x,minn);
x=j;
minn=min(x,minn);
x=n+1-j;
minn=min(x,minn);
if(minn%2==1) a[i][j]='+';
else a[i][j]='.';
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j)
cout<<a[i][j];
cout<<endl;
}
}
my reward:对于任何一个点,通过比较他和最上面,最下面,最左边,最右边,这四个值的最小值,即能判断他是第几圈
day2
楼梯有 n阶,上楼可以一步上一阶,也可以一步上二阶。
但你不能连续三步都走两阶,计算走到第n阶共有多少种不同的走法。
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
long long int dp[110][3];
void solve(){
int n;
long long sum=0;
cin>>n;
dp[1][0]=1;
dp[2][1]=1;
dp[2][0]=1;
for(int i=3;i<=n;++i){
for(int j=0;j<3;++j)
dp[i][0]=dp[i][0]+dp[i-1][j];
dp[i][1]=dp[i][1]+dp[i-2][0];
dp[i][2]=dp[i][2]+dp[i-2][1];
}
for(int i=0;i<3;++i) sum+=dp[n][i];
cout<<sum;
}
int main(void) {
//int n;
//dp[0]=1;
//dp[1]=1;
//cin>>n;
//for(int i=2;i<=n;++i){
// dp[i]=dp[i-1]+dp[i-2];
// if(i>6) dp[i]=dp[i]-dp[i-7];
// if(i==6) dp[i]--;
//}
//cout<<dp[n];
solve();
return 0;
}
my reward:
1.找规律其实挺难找的,找了n年
2. d p [ i ] [ j ] dp[i][j] dp[i][j]表示走到第i层时连续跳两层了j次 则 d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] + d p [ i − 1 ] [ 1 ] + d p [ i − 1 ] [ 2 ] dp[i][0]=dp[i-1][0]+dp[i-1][1]+dp[i-1][2] dp[i][0]=dp[i−1][0]+dp[i−1][1]+dp[i−1][2] 因为是连续的嘛,所以从上一层跳过来只能跳一层,所以j肯定变为0了。
day3
有一条很长的数轴,一开始你在00的位置。接下来你要走n步,第i步你可以往右走ai或者bi。
问n步之后,0到m的每个位置,能不能走到?
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e5+5;
int f[110][N];
int a[110],b[110];
int main(void) {
int n,m;
f[0][0]=1;
cin>>n>>m;
for(int i=1;i<=n;++i){
cin>>a[i]>>b[i];
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(j>=a[i]){
if(f[i-1][j-a[i]]) f[i][j]=1;
}
if(j>=b[i]){
if(f[i-1][j-b[i]]) f[i][j]=1;
}
}
}
for(int i=0;i<=m;++i){
if(f[n][i]) cout<<1;
else cout<<0;
}
return 0;
}
my reward: f [ i ] [ j ] f[i][j] f[i][j]表示第几步能否走到j,若为1表示能走到,想到其实也挺easy的
一维的怎么写
for(int i=1;i<=n;++i){
for(int j=m;j>=0;--j){
int flag=0;
if(j>=a[i]){
if(f[j-a[i]]) {
f[j]=1;
flag=1;
}
else f[j]=0;
}
if(j>=b[i]&&flag==0){
if(f[j-b[i]]) f[j]=1;
else f[j]=0;
}
if(j<a[i]&&j<b[i]) f[j]=0;
}
if(i==1) f[0]=0;
}
for(int i=0;i<=m;++i){
if(f[i]) cout<<1;
else cout<<0;
reward:刚开始不开flag,就寄了,因为假如你满足了a,f[j]变成了1,但是你不满足b,f[j]就变回0了
day4
#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
map<string,int>people;
map<string,int>score;
int main(void) {
int n,m,k,s1;
string s,x,y;
cin>>n>>m>>k;
while(n--){
cin>>s;
people[s]=1;
}
while(m--){
cin>>s>>s1;
score[s]=s1;
}
while(k--){
cin>>s>>x>>y;
if(people[s]&&y=="AC") people[s]=people[s]+score[x];
}
map<string,int>::iterator it;
//map<int,map<string,int> >::iterator it;
//for(it=people.begin();it!=people.end();it++){
// if(it->second==0) continue;
// cout<<it->first<<" "<<it->second-1<<endl;
//}
for(auto a:people){
if(a.second!=0) //敲重点!!!!!map循环遍历用second,first控制
cout<<a.first<<" "<<a.second-1<<endl;
}
return 0;
}
//这个写法没考虑到map会按键进行排序,所以输出的时候没按题中输入顺序输出,所以考虑在map前面在加一个参数来记录输入顺序
#include <bits/stdc++.h>
using namespace std;
map<int,map<string,int> >people;
map<string,int>score;
int main(void){
int n,m,k;
int score1;
string str,str1,str2;
cin>>n>>m>>k;
for(int i=1;i<=n;++i) {
cin>>str;
people[i][str]=1;//敲重点
}
for(int i=1;i<=m;++i){
cin>>str>>score1;
score[str]=score1;
}
while(k--){
cin>>str>>str1>>str2;
if(str2=="AC"){
for(int i=1;i<=n;++i){
if(people[i][str]>0){
people[i][str]+=score[str1];
break;
}
}
}
}
for(int i=1;i<=n;++i){
for(auto t:people[i]){
if(t.second>0) cout<<t.first<<" "<<t.second-1<<endl;//因为初始化1,所以这里要剪掉1
}
}
return 0;
}
#include <map>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
map<string,map<string,int>>people;
map<string,int>score;
int n,m,k;
int main(void) {
cin>>n>>m>>k;
vector<string>names(n);
for(int i=0;i<n;++i) cin>>names[i];
for(int i=0;i<m;++i){
int num;
string str;
cin>>str>>num;
score[str]=num;
}
for(int i=0;i<k;++i){
string name,pro,flag;
cin>>name>>pro>>flag;
if(flag=="AC") people[name][pro]=score[pro];//敲重点,不管第一维是int还是string,上面那个代码是int
}
for(int i=0;i<n;++i){
int sum=0;
for(auto j : people[names[i]]) sum+=j.second;
cout<<names[i]<<" "<<sum<<endl;
}
return 0;
}
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
map<int, string> row;//记录顺序
map<string, int>check;//记录有无出现
map<string, int>score;
map<string, int >ans;//记录答案
const int N = 1e5 + 10;
int ch[N];
int main(void) {
int n, m, k, x;
string str;
string a, b, c;
cin >> n >> m >> k;
for (int i = 1; i <= n; ++i) {
cin >> row[i];
check[row[i]] = 1;
}
while (m--) {
cin >> str >> x;
score[str] = x;
}
while (k--) {
cin >> a >> b >> c;
if (c == "AC" && score[b] && check[a]) ans[a] = ans[a] + score[b];
}
for (int i = 1; i <= n; ++i) {
cout << row[i] << " " << ans[row[i]] << "\n";
}
return 0;
}
think:还是关注auto的用法,map,vector都可以用的,再关注map套map的用法之类的,都是第一次见
第三种做法是添加一个数组来记录输入的字符串,最后循环这个字符串即可
107 饿饿饭饭
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],c[N];
int n;
typedef long long ll;
#define int long long
ll er(int mid){
int ans=0;
for(int i=1;i<=n;++i){
if(a[i]>mid) ans+=mid;
else ans+=a[i];
}
return ans;
}
signed main(void) {
int maxx=0;
ll k;
cin>>n>>k;
ll sum=0;
for(int i=1;i<=n;++i){
cin>>a[i];
sum+=a[i];
if(a[i]>maxx) maxx=a[i];
}
if(sum<k){
cout<<-1;
return 0;
}
int l=0,r=maxx+1;//二分好迷啊,
while(l<r){
int mid=(l+r+1)/2;//mid代表完整打完的有几轮
if(er(mid)<=k) l=mid;
else r=mid-1;
}
//cout<<l<<endl;
k-=er(l);
int tot=0,area,ans=0;
for(int i=1;i<=n;++i){
if(ans==k) {
area=i;
break;
}
if(a[i]==l+1) ans++;
if(a[i]>l+1) {
ans++;
c[++tot]=i;
}
}
//cout<<k<<" "<<area<<endl;
for(int i=area;i<=n;++i){
if(a[i]>l) cout<<i<<" ";
}
for(int i=1;i<=tot;++i){
cout<<c[i]<<" ";
}
return 0;
}
think:学习一下二分的思想,二分完整的能打几轮
还有就是long long这一点,卡了很久,我也不知道为什么必须要long long
201
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
int start;
int end;
int valve;
}n[1002];
int f[1002];
int main(void){
int t,x,y,z;
cin>>t;
for(int i=1;i<=t;++i){
cin>>x>>y>>z;
n[i].start=x;
n[i].end=y;
n[i].valve=z;
}
for(int i=1;i<=1000;++i){
for(int j=1;j<=t;++j){
if(n[j].end==i) f[i]=max(f[i],f[n[j].start]+n[j].valve);
else f[i]=max(f[i-1],f[i]);
}
}
cout<<f[1000];
return 0;
}
202
#include <bits/stdc++.h>
using namespace std;
long long ch[102][102],dp[102][102];
const int mod=1e9+7;
int main(void){
dp[1][1]=1;
int n;
cin>>n;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j)
cin>>ch[i][j];
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(i==1&&j==1) continue;
if(ch[i][j]==0) dp[i][j]=0;
else dp[i][j]=(dp[i-1][j]+dp[i][j-1])%mod;
// cout<<dp[i][j]<<" ";
}
// cout<<endl;
}
cout<<dp[n][n];
return 0;
}
203 最大和上升子序列
#include <bits/stdc++.h>
using namespace std;
int a[1010],f[1010];
int main(void) {
int n;
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i){
f[i]=a[i];//记得初始化,以自身结尾的也是一个子序列
for(int j=1;j<i;++j){
if(a[j]<a[i]) f[i]=max(f[i],f[j]+a[i]);
}
}
int maxx=0;//记得枚举,因为并不知道以哪个结尾的是最大的,刚开始直接cout f[n]导致错了
for(int i=1;i<=n;++i){
if(f[i]>maxx) maxx=f[i];
}
cout<<maxx;
return 0;
}
205 跳跳
#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
set<pair<int,int> >mp;//敲重点!!!set里面放pair
//map<int,vector<int> >mp;
int ch[510][2];
int gcd(int x,int y){
return y==0?x:gcd(y,x%y);
}
int main(void) {
int n;
cin>>n;
for(int i=1;i<=n;++i){
cin>>ch[i][0]>>ch[i][1];
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(i!=j){
int x=ch[i][0]-ch[j][0];
int y=ch[i][1]-ch[j][1];
// mp.insert(pair<int,int>(x/gcd(x,y),y/gcd(x,y)));
//mp.insert(make_pair(x/gcd(x,y),y/gcd(x,y)));
mp.insert({x/gcd(x,y),y/gcd(x,y)});//这几种写法都可以的
}
}
}
cout<<2*mp.size();
return 0;
}
reward:因为最后涉及到统计个数,并需要去重,所以想到用set或者map,但是set里面存两个的写法不会,是用pair来存的,
这题的思想就是全部转化为最小的步数,比如2,4可以转成1,2走两次
106 订单编号
#include <bits/stdc++.h>
#include <set>
using namespace std;
set<pair<int,int> >s;
void insert(int l,int r){
if(l>r) return;//如果前面的比后面的大,就不插入
else s.insert(make_pair(r,l));
}
int main(void){
int n,x;
cin>>n;
s.insert({2e9,1});//set有排序的功能,然后要对r排序,所以把r放在第一个参数
while(n--){
cin>>x;
auto iter=s.lower_bound(make_pair(x,0));//get 新知识,iter是指针类型,前面用auto,反正我用int 编译过不了,而且lower_bound还能这么用的,直接s.lowerbound,找第一个大于等于x的
if(iter->second<=x){
cout<<x<<" ";
insert(iter->second,x-1);//把小的放前面,如果前面的比后面的大,说明不符合了,就不插入
insert(x+1,iter->first);
s.erase(iter);//为什么删的是指针呢,我是想把整个pair删掉
}
else {
cout<<iter->second<<" ";
insert(iter->second+1,iter->first);
s.erase(iter);
}
}
return 0;
}
为什么要大的放前面呢,因为lower_bound找的是第一个大于等于的,如果小的放前面,找的区域就是所要的下一个区域了
pair的写法,make_pair或者是{l,r}
206 异或和或
#include <bits/stdc++.h>
using namespace std;
int main(void){
int t;
string str1,str2;
cin>>t;
while(t--){
int sum1=0,sum2=0;
cin>>str1>>str2;
int len1=str1.size();
int len2=str2.size();
if(len1!=len2) {
cout<<"NO"<<"\n";
continue;
}
for(int i=0;i<len1;++i){
if(str1[i]=='1') sum1++;
if(str2[i]=='1') sum2++;
}
if(sum1==0&&sum2==0) cout<<"YES"<<"\n";
else if(sum1>=1&&sum2>=1) cout<<"YES"<<"\n";
else cout<<"NO"<<"\n";
}
return 0;
}
发现如果序列中有1个1,那么他就可以变成很多个1,所以如果两个序列中都有1的话,那么就可以相互转化。反之,如果一个序列有1,另一个序列没有1,就不能转化
207 01序列
还需理解理解
#include <bits/stdc++.h>
#include <cstring>
using namespace std;
#define int long long
const int N=1e6+10;
char s[N];
int cnt[N];
int f[N];
signed main(void){
int k,ans=0;
scanf("%lld",&k);
getchar();
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;++i){
f[i]=f[i-1]+s[i]-'0';//记录前缀和
}
cnt[0]=1;
for(int i=1;i<=len;++i){
if(f[i]>=k) ans+=cnt[f[i]-k];//答案为前i个中,大小为i-k的子串的个数
cnt[f[i]]++;//cnt代表前i个中等于f[i]的子串有多少个
}
printf("%lld",ans);
return 0;
}
首先是前缀和,好像010100这样的用前缀和挺常见的,但是想到前缀和还是On2的复杂度,
与暴力找1 两层for循环没什么区别
加一
#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
vector<int>g;
const int N=2e2+10;
const int mod=1e9+7;
int vis[N],ans[10][N];
int main(void) {
int n;
cin>>n;
for(int i=0;i<=9;++i){
g.clear();
memset(vis,0,sizeof(vis));
int sum=0;
g.push_back(i);
for(int j=1;j<=20;++j){
int cnt=0;
for(int k=0;k<g.size();++k){
if(g[k]!=9) g[k]++;
else{
if(vis[k]==0){
sum++;
cnt++;//一开始没考虑到导致打表错误导致转移方程写错,因为push之后容器的size就会变大,导致循环会多执行几次
vis[k]=1;
}
}
}
while(cnt--){
g.push_back(0);
g.push_back(1);
}
ans[i][j]=g.size()-sum;
}
}
for(int i=0;i<=9;++i){
for(int j=1;j<=20;++j) cout<<ans[i][j]<<" ";
cout<<endl;
}
return 0;
}
首先因为没看出来,所以打表找规律,从而来找动态转移方程,不过i等于9时的方程不太好找,纯靠眼去找挺难
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=2e5+5,P=1e9+7;
int dp[10][N];//记录0-9的数字经过j次之后的长度
void init(){
for(int i=0;i<=9;++i) dp[i][0]=1;
for(int j=1;j<=200000;++j)
for(int i=0;i<=9;++i)
if(i==9) dp[9][j]=(dp[1][j-1]+dp[0][j-1])%P;
else dp[i][j]=dp[i+1][j-1];
}
void solve(){
int n,m; scanf("%d %d",&n,&m);
int ans=0;
while(n){
ans=(ans+dp[n%10][m])%P;
n/=10;
}
printf("%d\n",ans);
}
int main(){
init();
int T; scanf("%d",&T); while(T--) solve();
return 0;
}
302 序列维护
#include <bits/stdc++.h>
#include <vector>
using namespace std;
vector<int>G;
int main(void){
int n,x,y;
cin>>n;
string str;
while(n--){
cin>>str;//字符串读入,遇到空格停下,而且前面不用getchar,不同于getline(应该吧不确定)
if(str=="insert"){//string类型支持直接等于比较
cin>>x>>y;
G.insert(G.begin()+x,y);
}
else if(str=="query"){
cin>>x;
cout<<G[x-1]<<endl;
}
else if(str=="delete"){
cin>>x;
G.erase(G.begin()+x-1);//???????删除第几个元素
}
}
return 0;
}
如果想到用vector就比较简单了,刚开始想队列去了,熟悉一下vector的相关操作,并且字符串的读入以及比较,
整齐数组
#include <bits/stdc++.h>
using namespace std;
int a[50];
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
int main(void){
int t,n;
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
}
sort(a+1,a+1+n);
int first=1,ans;
for(int i=2;i<=n;++i){
if(first&&a[i]!=a[1]){
ans=a[i]-a[1];
first=0;
}
else if(a[i]!=a[1]) ans=gcd(ans,a[i]-a[1]);
}
if(first==1) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}
首先是所有的数都可以化成最小的数,即最后整齐的数一定是输入中的最小数。搞清楚这点之后就可以找她们与最小的数的最大公约数即可
305删删
#include<bits/stdc++.h>
using namespace std;
int solve(char s[],int n)
{
int f=0,ans=100000;
for(char c='a';c<='z';c++)
{
int l=0,r=n-1,cnt=0;
while(l<r)
{
if(s[l]==s[r]) l++,r--;
else if(s[l]==c) l++,cnt++;
else if(s[r]==c) r--,cnt++;
else break;
}
if(l>=r) ans=min(ans,cnt),f=1;
}
if(f) return ans;
return -1;
}
const int M=2e5+5;
char s[M];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int sl;
scanf("%d",&sl);
scanf("%s",s);
printf("%d\n",(solve(s,sl)));
}
return 0;
}
饿饿饭饭2
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
const int N=2e5+10;
int ans[N];
int main(void){
int t,n,x;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&x);
while(x%2==0||x%3==0){
if(x%2==0) x=x/2;
if(x%3==0) x=x/3;
}
ans[i]=x;
}
int flag=1;
sort(ans+1,ans+1+n);
for(int i=1;i<=n-1;++i){
if(ans[i]!=ans[i+1]){
flag=0;
break;
}
}
if(flag) cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
}
return 0;
}
一个数乘2乘3最后成为相等的,那么把他化成 x = 2 a ∗ 3 b ∗ h h h x=2^a*3^b*hhh x=2a∗3b∗hhh(hhh中不含有2的因子,不含有3的因子) 所以两个数如果最后能化成一样的话,那么他们的hhh肯定是一样的,明白这一点后就好实现了,把所有数的hhh找出来比较是否相等即可
401子串分支和
1.很普通的想法,比如是 a b a b c ababc ababc
a b a b c
ab ba ab c
aba bab abc
abab babc
ababc
但是子串长度为1e6 这样两层for循环肯定超时
2.考虑a所在的子串有多少个,b所在的子串有多少个,c所在的子串有多少个,三者相加即可
那a所在的子串有多少个呢,直接算不好算吧,考虑所有的子串减去a不在的子串就是a所在的子串
#include <bits/stdc++.h>
#include <cstring>
using namespace std;
const int N=1e6+10;
char str[N];
int main(void){
scanf("%s",str+1);
int len=strlen(str+1);//!!!!!!!!!!!!!!!必须要str+1哦,因为上面读入的时候是str+1
long long ans=0;
for(int i=97;i<=97+25;++i){
char s=i;
long long flag=0;
long long sum=0;
for(int j=1;j<=len;++j){
if(str[j]==s) {
sum=sum+1LL*(j-flag)*(j-flag-1)/2;//!!!!!!!!
flag=j;
}
}
sum=sum+1LL*(len+1-flag)*(len-flag)//2;!!!!!!!!!!大数相乘爆int了的
ans=ans+1LL*len*(len+1)/2-sum;//!!!!!!!!!
}
//实验了一下,发现只要把len的类型改为long long下面即可不用加1LL 或者直接#define int long long
//还有就是1LL变成(long long) 后面无需加括号,如果把后面两个相乘再加上括号就错了
cout<<ans;
return 0;
}
402
#include <bits/stdc++.h>
#include <set>
using namespace std;
const int N=1e6+10;
set<pair<int,int> >s1,s2;
bool jia[N],kou[N];
int main(void){
int n,op,w,t;
long long sum=0;
cin>>n;
while(n--){
cin>>op;
if(op==1){
cin>>w>>t;
if(jia[w]||kou[t]) continue;
s1.insert(make_pair(w,t));//以价格为关键字
s2.insert((make_pair(t,w)));
jia[w]=true;
kou[t]=true;
}
else if(op==2){
set<pair<int,int>>::iterator iter;
iter=s1.begin();//这里其实不用这么麻烦的,但也是一种方法,见下文
int x=iter->first;
int y=iter->second;
s1.erase(iter);
s2.erase(make_pair(y,x));
jia[x]=false;
kou[y]=false;
}
else if(op==3){
set<pair<int,int>>::iterator iter;
iter=s2.begin();
int x=iter->first;
int y=iter->second;
s2.erase(iter);
s1.erase(make_pair(y,x));
jia[y]=false;
kou[x]=false;
}
}
set<pair<int,int>>::iterator iter;
for(iter=s1.begin();iter!=s1.end();++iter){
sum=sum+iter->first;
}
cout<<sum;
return 0;
}
#include <bits/stdc++.h>
#include <set>
using namespace std;
const int N=1e6+10;
set<int>w1;
set<int>t1;
int w_t[N];//价格对应的口感
int t_w[N];//口感对应的价格,因为w,t有范围,可以用数组存
int main(void){
int n,op,w,t;
int sum=0;
cin>>n;
while(n--){
cin>>op;
if(op==1){
cin>>w>>t;
if(w_t[w]||t_w[t]) continue;
w_t[w]=t;
t_w[t]=w;
w1.insert(w);
t1.insert(t);
}
else if(op==2){
w=*w1.begin();
w1.erase(w1.begin());//这样不用迭代
t=w_t[w];
t1.erase(t);
w_t[w]=0;
t_w[t]=0;
}
else if(op==3){
t=*t1.begin();
t1.erase(t1.begin());
w=t_w[t];
w1.erase(w);
w_t[w]=0;
t_w[t]=0;
}
}
for(auto i:w1){
sum+=i;
}
cout<<sum;
return 0;
}
#include <bits/stdc++.h>
#include <map>
using namespace std;
const int N=1e5+10;
map<int,int>w_t;
map<int,int>t_w;//脑残加了个参数
int main(void){
int n,op,w,t,sum=0;
cin>>n;
while(n--){
cin>>op;
if(op==1){
cin>>w>>t;
if(w_t.count(w)||t_w.count(t)) continue;//这里如果改成if(w_t[w]||t_w[t])就有问题
//map中会自动生成一个0,然后会对程序哪里有影响呢,别用那种就行了,记得找某个元素用count就行
w_t[w]=t;
t_w[t]=w;
}
else if(op==2){
t_w.erase(w_t.begin()->second);
w_t.erase(w_t.begin());
}
else if(op==3){
w_t.erase(t_w.begin()->second);//上下顺序不能换哦
t_w.erase(t_w.begin());
}
}
for(auto i:w_t){
sum=sum+i.first;
}
cout<<sum;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
set < pair<int ,int > > a,b;
int n,op,w,t;
long long ans;
int main(){
scanf("%d",&n);
while(n--){
scanf("%d",&op);
if(op==1){
scanf("%d%d",&w,&t);
auto itr=a.lower_bound(make_pair(w,0));
if(itr!=a.end()&&itr->first==w)continue;
itr =b.lower_bound(make_pair(t,0));
if(itr!=b.end()&&itr->first==t)continue;
a.insert(make_pair(w,t));
b.insert(make_pair(t,w));
}
if(op==2){
auto it=a.begin();//省去了迭代器,直接auto
int x=it->first,y=it->second;
//auto it1=b.find(make_pair(y,x));
a.erase(make_pair(x,y));b.erase(make_pair(y,x));
}
if(op==3){
auto it2=b.begin();
int x1=it2->first,y1=it2->second;
//auto it3=a.find(make_pair(y1,x1));
b.erase(make_pair(x1,y1));a.erase(make_pair(y1,x1));
}
}
for(auto itr=a.begin();itr!=a.end();itr++){
//printf("%d\n",itr->first);
ans+=itr->first;
}
printf("%lld",ans);
return 0;
}
展示一下map寻找有无值方法,发现size会变多,从本来的0变成了100
锦标赛(思维题哇)
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main(void){
int n,k,sum=1;
cin>>n>>k;
for(int i=1;i<=n;++i) cin>>a[i];
sort(a+1,a+1+n);
for(int i=n;i>=2;--i){
if(a[i]-a[i-1]>k) break;
sum++;
}
cout<<sum;
return 0;
}
排一下序,从后往前找,找到大于k的就退出了
404 可重排列
(简单题,只要会用next_permutation)
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main(void){
int n,x;
cin>>n;
int k=0;
for(int i=1;i<=n;++i){
cin>>x;
for(int j=1;j<=x;++j){
a[k++]=i;
}
}
do{
for(int i=0;i<k;++i) cout<<a[i]<<" ";
cout<<"\n";
}while(next_permutation(a,a+k));
return 0;
}