简单模拟选做 & C++特性

海港

重点在于想到我们不关心每个人是第几批次,不关心同一时间同一国籍有几个人,所以可以只储存去重后的每个人的国籍和时间信息。

使用queue和map和pair,stl就是好用(

#include<iostream>
#include<cstdio>
#include<queue>
#include<map>
using namespace std;
const int N=200000;
int n,t[N];
queue<pair<int,int>>q,p;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
int k;scanf("%d%d",&t[i],&k);
map<int,int>m;
for(int j=1;j<=k;++j){
int x;scanf("%d",&x);
if(m[x]) continue;
m[x]=1;
q.push(make_pair(t[i],x));
}
}
map<int,int>m1;
for(int i=1;i<=n;++i){
while(p.front().first<=t[i]-86400&&!p.empty()){
if(--m1[p.front().second]==0) m1.erase(p.front().second);
p.pop();
}
while(q.front().first<=t[i]&&!q.empty()){
++m1[q.front().second];
p.push(q.front());q.pop();
}
printf("%d\n",m1.size());
}
return 0;
}

Home

题意:给定序列an和常数p,求

Σi=1n(2|xai|+px)

的最小值

解法:三分法求单峰函数极值,略卡常

#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
const int N=1000010;
int n,p;
int a[N];
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline ll cal(ll x){
ll ans=p*x;
for(int i=1;i<=n;++i){
ans+=abs(a[i]-x)*2;
}
return ans;
}
inline int tri(int l,int r){
if(l==r) return l;
if(r-l==1){
ll cl=cal(l),cr=cal(r);
if(cl<=cr) return l;
return r;
}
if(r-l==2){
ll c1=cal(l),c2=cal((l+r)/2),c3=cal(r);
if(c1<=c2&&c1<=c3) return l;
if(c2<=c3) return (l+r)/2;
return r;
}
int m1=l+(r-l)/3,m2=r-(r-l)/3;
ll c1=cal(m1),c2=cal(m2);
if(c1>c2) return tri(m1,r);
return tri(l,m2);
}
int main(){
int T;T=read();while(T--){
// scanf("%d%d",&n,&p);
n=read();p=read();
int l=N,r=-N;
for(int i=1;i<=n;++i){
// scanf("%d",&a[i]);
a[i]=read();
l=min(l,a[i]);r=max(r,a[i]);
}
if(abs(p)>n*2) {printf("No\n");continue;}
if(abs(p)==n*2&&p>0) {printf("No\n");continue;}
int ans=tri(l,r);
printf("%d\n",ans);
}
return 0;
}

计算器的改良

注意一点细节:a+2a=4这个式子a默认系数是1;-2x=0解出来会x=-0.000,需要特判。。。

#define eps 0.000006
int main(){
char n,x;int a=0,b=0,c=0,d=0,flag=0,tmp=0,minus=1;double ans;
while(n=getchar()){
if(n>='0'&&n<='9') tmp=tmp*10+n-'0';
else{
tmp*=minus;
if(n>='a'&&n<='z'){
x=n;
if(tmp==0) tmp=1;
if(flag) c+=tmp;
else a+=tmp;
}else{
if(flag) d+=tmp;
else b+=tmp;
}tmp=0;minus=1;
if(n=='=') flag=1;
if(n=='-') minus=-1;
}
if(n=='\n') break;
} ans=1.0*(d-b)/(a-c);
if(fabs(ans)<eps) ans=0.0;
printf("%c=%.3lf",x,ans);
return 0;
}

跳房子

二分答案,需要维护RMQ,强制在线

维护RMQ有很多方法,最简单的ST表、单调队列、线段树,还有比较高级的FourRussian和笛卡尔树。这里ST表会爆空间(O(n2)

因此使用deque实现单调队列维护RMQ,每次判断复杂度为线性,总复杂度O(nlogX)

不知道有没有什么更优雅的方法可以给f数组赋初始值,0x3f到底是什么原理?

感觉我的代码重构能力有待提升,不过最好还是 think twice code once 吧

这道题是NOIP2017普及组T4,也是我第一年参加普及组,没想到现在才补完题w

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int inf=1000000000;
int n,d,k,maxx,b_;
int x[1000000],s[1000000];
ll f[1000000];
deque<int> q;
bool solve(int g){
q.clear();memset(f,-0x3f,sizeof(f));f[0]=0;q.push_back(0);
int now=1;
for(int i=1;i<=n;++i){
int l=max(0,x[i]-(d+g)),r=min(x[i]-1,x[i]-(d-g));
if(r<0) continue;
while(!q.empty()&&x[q.front()]<l) q.pop_front();
while(x[now]<=r){
while(x[now]<l) ++now;
while(!q.empty()&&f[q.back()]<=f[now]) q.pop_back();
q.push_back(now);++now;
}
if(!q.empty()) f[i]=f[q.front()]+s[i];
if(f[i]>=k) return b_=1;
}
return 0;
}
int main(){
cin>>n>>d>>k;
for(int i=1;i<=n;++i) {cin>>x[i]>>s[i];maxx=max(maxx,x[i]);}
int l=0,r=maxx;while(l<=r){
int mid=(l+r)/2;
if(solve(mid)) r=mid-1;
else l=mid+1;
}
if(b_) cout<<l<<endl;
else cout<<-1<<endl;
return 0;
}

求和

这个求和公式 (x+z)(numberx+numberz) 果然是暗藏玄机

首先注意到三元组的分数与中间项无关,考虑分奇偶分别处理首尾项。把每种颜色单独提取出来,两两加和计算贡献,复杂度 O(n2)

考虑优化:

xinumi=(n1)xinumi+ijxinumj=(n2)xinumi+xinumi

单独验证一下 n=1 和 n=2 符合,这样可以优化到O(nlogn) ,log是我用优先队列筛选颜色整出来的,也可以用空间换时间优化到 O(n)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=200000,mod=10007;
int n,m,ans;
struct node{
int x,num,clr;
bool operator <(const node &temp)const{
return clr<temp.clr;
}
};
priority_queue<node>q0,q1;
int tmp1[N],tmp2[N];
signed main(){
cin>>n>>m;
for(int i=1;i<=n;++i) cin>>tmp1[i];
for(int i=1;i<=n;++i) cin>>tmp2[i];
for(int i=1;i<=n;++i){
node tmp={i,tmp1[i],tmp2[i]};
if(i%2) q1.push(tmp);
else q0.push(tmp);
}
while(!q0.empty()){
node now=q0.top();q0.pop();
if(q0.empty()) break;
int sum=now.x*now.num,sumx=now.x,sumn=now.num,cnt=1;
while(q0.top().clr==now.clr){
node t=q0.top();q0.pop();
sum+=t.x*t.num;sumx+=t.x;sumn+=t.num;
++cnt;
if(q0.empty()) break;
}
ans=(ans+(cnt-2)*sum+sumx*sumn)%mod;
}
while(!q1.empty()){
node now=q1.top();q1.pop();
if(q1.empty()) break;
int sum=now.x*now.num,sumx=now.x,sumn=now.num,cnt=1;
while(q1.top().clr==now.clr){
node t=q1.top();q1.pop();
sum+=t.x*t.num;sumx+=t.x;sumn+=t.num;
++cnt;
if(q1.empty()) break;
}
ans=(ans+(cnt-2)*sum+sumx*sumn)%mod;
}
cout<<ans<<endl;
return 0;
}

求交集

题目链接

#include<iostream>
#include<cstdio>
#include<vector>
#include<sstream>
#include<algorithm>
#include<set>
using namespace std;
int main(){
string A, B, tmp;
getline(cin, A);getline(cin, B);
istringstream Astream(A), Bstream(B);
vector<int> a, b, c;
while(getline(Astream, tmp, ',')) a.push_back(stoi(tmp));
while(getline(Bstream, tmp, ',')) b.push_back(stoi(tmp));
for(int i = 0; i < a.size(); ++i){
for(int j = 0; j < b.size(); ++j){
if(a[i] == b[j]) c.push_back(a[i]);
}
}
if(c.empty()) cout<<"NULL"<<endl;
else{
sort(c.begin(), c.end());
cout<<c[0];
for(int i = 1; i < c.size(); ++i)
if(c[i]!=c[i-1])
cout<<','<<c[i];
}
}

根据日期求星期:

题目链接

ctime库

#include <iostream>
#include <ctime>
#include <cstring>
using namespace std;
const string week[8] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
bool f(string x, string y){
int lenx = x.length(), leny = y.length();
for(int i = 0; i + leny <= lenx; ++i){
if(x.substr(i, leny) == y) return 1;
}
return 0;
}
int getMonth(string x){
if(f(x, "Jan")) return 1;
if(f(x, "Feb")) return 2;
if(f(x, "Mar")) return 3;
if(f(x, "Apr")) return 4;
if(f(x, "May")) return 5;
if(f(x, "Jun")) return 6;
if(f(x, "Jul")) return 7;
if(f(x, "Aug")) return 8;
if(f(x, "Sep")) return 9;
if(f(x, "Oct")) return 10;
if(f(x, "Nov")) return 11;
if(f(x, "Dec")) return 12;
return -1;
}
int getYear(string x){
int a[3], cnt = 0;
for(int i = 0; i < x.length(); ++i)
if(x[i] == '-') a[++cnt] = i;
if(a[1] == 4) return stoi(x.substr(0, 4));
if(a[2] == 6) return stoi(x.substr(7, 4));
return stoi(x.substr(a[1]+1, 4));
}
int getDay(string x){
int a[3], cnt = 0;
for(int i = 0; i < x.length(); ++i)
if(x[i] == '-') a[++cnt] = i;
if(a[1] == 2) return stoi(x.substr(0, 2));
if(a[2] == 8) return stoi(x.substr(9, 2));
return stoi(x.substr(a[1]+1, 2));
}
int main() {
int T;cin>>T;
while(T--){
string a;cin>>a;
int mon = getMonth(a),
day = getDay(a),
year = getYear(a);
// cout<<mon<<' '<<day<<' '<<year<<endl;
struct tm date = {};
date.tm_year = year - 1900;
date.tm_mon = mon - 1;
date.tm_mday = day;
time_t t = mktime(&date);
tm* localTime = localtime(&t);
cout<<week[localTime->tm_wday]<<'.'<<endl;
}
return 0;
}

好人坏人

约瑟夫,但是不需要考虑具体的位置,只需要考虑是否位于前k个即可

原文链接

#include <iostream>
#include <cstdio>
using namespace std;
int solve(int k, int m) {
int cur = 0, now = k * 2;
while(now > k){
cur = (cur - 1 + m) % now;
if(cur < k) return 0;
--now;
}return 1;
}
int main() {
int k; cin >> k;
while (k) {
for (int i = 2; ; ++i) {
if (solve(k, i)) {
cout << i << endl;
break;
}
}
cin >> k;
}
return 0;
}

[ZJOI2008]泡泡堂

双指针对田忌和齐威王的马进行比较,每次贪心选择看起来最好的方案。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n, a[200000], b[200000];
bool cmp(int x, int y){
return x > y;
}
int f(int* a, int* b){
int la = 1, ra = n, lb = 1, rb = n, ans = 0;
for(int i = 1; i <= n; ++i){
if(a[la] > b[lb]){
++la;++lb;++ans;
}else if(a[la] < b[lb]){
--ra;++lb;--ans;
}else{
if(a[ra] < b[rb]){
--ra;++lb;--ans;
}else if(a[ra] > b[rb]){
--ra;--rb;++ans;
}else{
if(a[ra] < b[lb]){
--ans;
}
--ra;++lb;
}
}
}
return ans + n;
}
int main(){
// while(1){
cin>>n;
// if(n == 0) break;
for(int i = 1; i <= n; ++i) cin>>a[i]; //Tianji
for(int i = 1; i <= n; ++i) cin>>b[i]; //Qiweiwang
sort(a + 1, a + n + 1, cmp);sort(b + 1, b + n + 1, cmp);
cout<<f(a, b)<<' '<<n * 2 - f(b, a)<<endl;
// }
return 0;
}

四则运算表达式的值

处理了左括号右边是正负号和等式开头是正负号的情况,并且把中缀转后缀和后缀表达式求值合并到一起进行。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
int judge(char ch){
if(ch == '+' || ch == '-') return 1;
if(ch == '*' || ch == '/') return 2;
if(ch == '(' || ch == ')') return 0;
if(ch >= '0' && ch <= '9') return -1;
return -2;
}
int suf(string str){
string ans;
stack<int> nums;
stack<char> opers;
if(judge(str[0]) > 0) nums.push(0);
for(int i = 0; i < str.length(); ++i){
int typ = judge(str[i]);
if(typ == -1){
string tmp;tmp += str[i];
while(judge(str[i + 1]) == -1) tmp += str[++i];
nums.push(stoi(tmp));
}else if(typ > 0){
if(opers.empty() || judge(opers.top()) < typ){
opers.push(str[i]);
}else{
while(!opers.empty() && judge(opers.top()) >= typ){
char oper = opers.top();opers.pop();
int y = nums.top();nums.pop();
int x = nums.top();nums.pop();
if(oper == '+') nums.push(x + y);
if(oper == '-') nums.push(x - y);
if(oper == '*') nums.push(x * y);
if(oper == '/') nums.push(x / y);
}
opers.push(str[i]);
}
}else if(str[i] == '('){
if(judge(str[i + 1]) > 0) nums.push(0);
opers.push('(');
}else if(str[i] == ')'){
char oper = opers.top();opers.pop();
while(oper != '('){
int y = nums.top();nums.pop();
int x = nums.top();nums.pop();
if(oper == '+') nums.push(x + y);
if(oper == '-') nums.push(x - y);
if(oper == '*') nums.push(x * y);
if(oper == '/') nums.push(x / y);
oper = opers.top();opers.pop();
}
}
}
while(!opers.empty()){
char oper = opers.top();opers.pop();
int y = nums.top();nums.pop();
int x = nums.top();nums.pop();
if(oper == '+') nums.push(x + y);
if(oper == '-') nums.push(x - y);
if(oper == '*') nums.push(x * y);
if(oper == '/') nums.push(x / y);
}
return nums.top();
}
int main() {
string str;
while(cin>>str)
cout<<suf(str)<<endl;
return 0;
}

愉悦的假期(USACO11NOV)

分两种情况,一种是三个块两两连接,一种是一个点直接连三个块。

第一种情况n4的枚举每两个点然后计算距离并统计,第二种情况对每个空点n2的枚举X点,先标记后统计。总复杂度O(n4)

#include <iostream>
#include <queue>
#include <utility>
#include <vector>
#include <map>
#include <cstring>
using namespace std;
//const int inf = 1e9;
const int N = 51;
int n, m, cnt = 0, maxx = 0;
char mp[N][N];
int fax[N][N], fay[N][N];
int ans[N][N][N][N];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
void dfs(int x, int y, int fx, int fy){
fax[x][y] = fx;fay[x][y] = fy;
for(int i = 0; i < 4; ++i){
int nx = x + dx[i], ny = y + dy[i];
if(mp[nx][ny] == 'X' && (fax[nx][ny] == 0 && fay[nx][ny] == 0))
dfs(nx, ny, fx, fy);
}
}
int main() {
cin>>n>>m;
for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) cin>>mp[i][j];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
if(mp[i][j] == '.') continue;
if(fax[i][j] && fay[i][j]) continue;
dfs(i, j, i, j);
}
for(int x1 = 1; x1 <= n; ++x1)
for(int y1 = 1; y1 <= m; ++y1){
if(mp[x1][y1] == '.') continue;
for(int x2 = 1; x2 <= n; ++x2)
for(int y2 = 1; y2 <= m; ++y2){
if(mp[x2][y2] == '.') continue;
if(fax[x1][y1] == fax[x2][y2] && fay[x1][y1] == fay[x2][y2]) continue;
int fx1 = fax[x1][y1], fy1 = fay[x1][y1], fx2 = fax[x2][y2], fy2 = fay[x2][y2];
if(ans[fx1][fy1][fx2][fy2] == 0) ans[fx1][fy1][fx2][fy2] = abs(x1-x2)+abs(y1-y2)-1;
else ans[fx1][fy1][fx2][fy2] = ans[fx2][fy2][fx1][fy1] = min(ans[fx1][fy1][fx2][fy2], abs(x1-x2)+abs(y1-y2)-1);
}
}
for(int x1 = 1; x1 <= n; ++x1)
for(int y1 = 1; y1 <= m; ++y1)
for(int x2 = 1; x2 <= n; ++x2)
for(int y2 = 1; y2 <= m; ++y2)
if(ans[x1][y1][x2][y2]){
if(x2 > x1 || (x2 == x1 && y2 > y1)) continue;
cnt += ans[x1][y1][x2][y2];
maxx = max(maxx, ans[x1][y1][x2][y2]);
}
cnt -= maxx;
int num = cnt;
map<pair<int, int>, int> man;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
if(mp[i][j] == 'X') continue;
man.clear();
for(int x = 1; x <= n; ++x)
for(int y = 1; y <= m; ++y){
if(mp[x][y] == '.') continue;
if(!man[make_pair(fax[x][y], fay[x][y])]) man[make_pair(fax[x][y], fay[x][y])] = abs(i-x)+abs(j-y);
else man[make_pair(fax[x][y], fay[x][y])] = min(man[make_pair(fax[x][y], fay[x][y])], abs(i-x)+abs(j-y));
}
int tmp = 0;
for(auto m : man) tmp += m.second;
num = min(num, tmp-2);
// cout<<man.size()<<' '<<m<<endl;
}
cout<<num<<endl;
return 0;
}
posted @   hcx1999  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示