昨天感觉效率也不是很高,可能我效率从来没很高过吧。可能一直在分神
昨天还是做的线性表,做了一天可算做完了!!
P1996 约瑟夫问题
这题看了标签之后才开始做的,看见是队列然后思路马上就有了。开2个队列来回就行。
其他做法:链表。
还是一样模拟,注意stl中end(),是不存在的!!!
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
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<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
list<ll>s;
int n,m;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
s.push_back(i);
}
list<ll>::iterator it=s.begin();
while(s.size()>1){
for(int i=1;i<m;i++){
it++;
if(it==s.end())it=s.begin();
}
cout<<*it<<" ";
it++;
list<ll>::iterator node=it;
if(node==s.end())node=s.begin();
s.erase(--it);
it=node;
}
cout<<*it<<endl;
return 0;
}
P1160 队列安排
频繁的填数和删除好像可以用列表吧。
填数如下操作
设一个迭代器数组
next()是求迭代器的下一个,而迭代器本身的位置不会变
list <ll>::iterator pos[100005];
for(int i=2;i<=n;i++){
cin>>k>>p;
if(p==0){
pos[i]=s.insert(pos[k],i);
}else{
list<ll>::iterator it=next(pos[k]);
pos[i]=s.insert(it,i);
}
}
删除数据
删除数组最好用erase,不要用remove,因为remove不是真正的删除,而是将要删除的数据放在最后了
for(int i=1;i<=m;i++){
ll x;
cin>>x;
if(vis[x]==1){
continue;
}else{
s.erase(pos[x]);
vis[x]=1;
}
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include<list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
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<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int n,k,p,m;
list<ll>s;
list <ll>::iterator pos[100005];
bool vis[100005];
int main(){
cin>>n;
s.push_back(1);
pos[1]=s.begin();
for(int i=2;i<=n;i++){
cin>>k>>p;
if(p==0){
pos[i]=s.insert(pos[k],i);
}else{
list<ll>::iterator it=next(pos[k]);
pos[i]=s.insert(it,i);
}
}
cin>>m;
for(int i=1;i<=m;i++){
ll x;
cin>>x;
if(vis[x]==1){
continue;
}else{
s.erase(pos[x]);
vis[x]=1;
}
}
list<ll>::iterator it;
for(it=s.begin();it!=s.end();++it){
cout<<*it<<" ";
}
return 0;
}
P2058 [NOIP2016 普及组] 海港
这题一直没搞懂怎么搞那个国家的人数,想过前缀和,但不行..
正确做法:
开一个vis[]数组来记录各个国家的人数,开一个结构体来记录国家和时间,
用队列存储每一艘船的信息:国家和时间
如果队列的时间不在24小时内,对vis数组更新,如果更新后vis[]=0,ans--
然后pop(),continue;如果满足条件就break;
入队列同理
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
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<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
struct Node{
ll nation,time;
}u;
int n,k,t;
ll vis[100005];
ll ans=0;
queue<Node>q;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>t>>k;
while(!q.empty()){
u=q.front();
if(t-u.time>=86400){
q.pop();
vis[u.nation]--;
if(vis[u.nation]==0)ans--;
continue;
}else{
break;
}
}
for(int j=1;j<=k;j++){
int x;
scanf("%d",&x);
u.nation=x;
u.time=t;
if(vis[x]==0)ans++;
vis[x]++;
q.push(u);
}
printf("%lld\n",ans);
}
return 0;
}
P2234 [HNOI2002] 营业额统计
一道绿题,但是暴力可以过...
正确做法:二分+set
在次之前我还不知道set可以二分...
k为迭代器,s为set、
k=s.lower_bound(x);
这题还有一点很妙的是,提前存入1个正的大数和负的大数
防止lower_bound()没有搜到,或者搜到的第一个位置为1
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
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<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
set<ll>s;
int n;
set<ll>::iterator a,k;
int main(){
ll x;
s.insert(192608170);
s.insert(-192608170);
cin>>n;
ll ans=0;
for(int i=1;i<=n;i++){
cin>>x;
if(i==1){
ans=ans+x;
s.insert(x);
}else{
k=s.lower_bound(x);
if(*k!=x){
a=k;
--a;
ans=ans+min(abs(*a-x),abs(*k-x));
s.insert(x);
}
}
}
cout<<ans;
return 0;
}