括号匹配
#include<bits/stdc++.h>
using namespace std;
char st[1100];
string s;
int top;
int main(){
cin>>s;
int len=s.size();
for(int i=0;i<len;i++){
if(s[i]=='['||s[i]=='('){
st[++top]=s[i];
}
else{
if(top==0){
cout<<"Wrong";
return 0;
}
if(s[i]==']'){
if(st[top]=='['){
top--;
}
}
if(s[i]==')'){
if(st[top]=='('){
top--;
}
}
}
}
if(top==0){
cout<<"OK";
}
else{
cout<<"Wrong";
}
return 0;
}
操作系统
#include<bits/stdc++.h>
using namespace std;
struct node{
int num,gtim,timed,you;
friend bool operator<(node a,node b){//重载运算符< (priority是反着的(即符合要求的往后放))
if(a.you!=b.you){
return a.you<b.you;
}
else{
return a.gtim>b.gtim;
}
}
};
long long ans;
int n,g,t,y,now;
priority_queue<node>q;
int main(){//小顶堆内放的是可以进行买入的操作的金额
while(cin>>n>>g>>t>>y){//还有新任务到达
while(!q.empty()&&now+q.top().timed<=g){
now+=q.top().timed;//省略了完成任务的时间
cout<<q.top().num<<" "<<now<<"\n";
q.pop();
}
if(!q.empty()){//时间不够
node x=q.top();//返回值不是引用,只能先取队头,改完再放进去(维护队列有序)
q.pop();
x.timed-=g-now;//先处理一部分,时间消耗为下一个任务到达时间-当前时间,所需时间减少
q.push(x);
}
now=g;//看作瞬间把这部分任务处理完,所花费的时间立刻减去(即新任务立刻到达)
q.push({n,g,t,y});//放进去后再进入下个循环
}
while(!q.empty()){//没有新任务到达
now+=q.top().timed;
cout<<q.top().num<<" "<<now<<"\n";
q.pop();
}
return 0;
}
序列
#include<bits/stdc++.h>
using namespace std;
int gcnt[51000],fcnt[51000],a[51000],f[51000],g[51000],sum[51000];
long long ans;
int n;
int t;
int lowbit(int t){//树状数组
return t&-t;
}
void updata(int cnt[],int x,int y){
for(int i=x;i<=n;i+=lowbit(i)){
cnt[i]+=y;
}
}
int getsum(int cnt[],int x){
int ff=0;
for(int i=x;i>=1;i-=lowbit(i)){
ff+=cnt[i];
}
return (long long)ff;
}
int main(){
scanf("%d",&t);
while(t--){
memset(gcnt,0,sizeof gcnt);
memset(fcnt,0,sizeof fcnt);
ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
f[i]=getsum(fcnt,a[i]);
updata(fcnt,a[i],1);
}
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+f[i];//前缀和
}
for(int i=n;i>=1;i--){
g[i]=getsum(gcnt,n)-getsum(gcnt,a[i]);
// cout<<getsum(a[i])<<"\n";
updata(gcnt,a[i],1);
}
// for(int i=1;i<=n;i++){
// cout<<f[i]<<" "<<g[i]<<"\n";
//}
for(int i=1;i<=n;i++){
ans+=(long long)g[i]*sum[i-1];//防止溢出
}
printf("%lld\n",ans);
}
return 0;
}
BIT-3
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long sum[1100000],cnt[1100000],a[1100000];
int lowbit(int t){
return t&-t;
}
void updata(int x,long long y){//开longlong
for(int i=x;i<=n;i+=lowbit(i)){
cnt[i]+=y;
sum[i]+=y*x;//要改变的元素+=c*x,TA的祖先跟着他也加c*k
}
}
long long getsum(int x){
long long ans=0;
for(int i=x;i>=1;i-=lowbit(i)){
ans+=cnt[i];
}
ans*=(x+1);
for(int i=x;i>=1;i-=lowbit(i)){
ans-=sum[i];
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
updata(i,a[i]);
updata(i+1,-a[i]);
}
while(m--){
int k,l,r,op;
scanf("%d%d%d",&op,&l,&r);
if(op==1){
scanf("%d",&k);
updata(l,k);
updata(r+1,-k);
}
else{
printf("%lld\n",getsum(r)-getsum(l-1));
}
}
return 0;
}
最长上升子序列
#include<bits/stdc++.h>
using namespace std;
int n,a[1100000],vis[1100000],dp[1100000],cnt[1100000],maxn=0,ans;
int lowbit(int t){//树状数组求前缀最大值
return t&-t;
}
void updata(int x,int y){
for(int i=x;i<=maxn;i+=lowbit(i)){
cnt[i]=max(cnt[i],y);
}
}
int getsum(int x){
int as=0;
for(int i=x;i>=1;i-=lowbit(i)){
as=max(as,cnt[i]);
}
return as;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]++;//把最小下标改成1
maxn=max(maxn,a[i]);
}
for(int i=1;i<=n;i++){
dp[i]=getsum(a[i]-1)+1;//a[i]-1:保证严格升序
updata(a[i],dp[i]);
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
return 0;
}
part:----差分
差分定义:
b[i]-a[i]-a[i-1];
差分数组求前缀和,结果是原数组
b[1]+b[2]+b[3]=a[3];
差分数组求区间和:
b[l]+=k,b[r+1]-=k;
本质:差分数组每个元素+=k,还原回原数组之后,后面的每个元素都多一个k
//不能被打断!!/不能在差分过程中 进行询问--(离线的)
BIT-2
#include<bits/stdc++.h>
using namespace std;
long long a[1100000],sum[1100000];
int n,q;
int lowbit(int t){//拿树状数组当差分数组用
return t&-t;
}
void updata(int x,int y){
for(int i=x;i<=n;i+=lowbit(i)){
sum[i]+=y;
}
}
long long getsum(long long x){
long long ans=0;
for(int i=x;i>=1;i-=lowbit(i)){
ans+=sum[i];
}
return ans;
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
updata(i,a[i]);
updata(i+1,-a[i]);//差分维护
}
while(q--){
long long l,r,k,op;
scanf("%lld",&op);
if(op==1){
scanf("%lld%lld%lld",&l,&r,&k);
updata(l,k);
updata(r+1,-k);//差分维护
}
else{
scanf("%lld",&k);
printf("%lld\n",getsum(k));
}
}
return 0;
}
模板链式前向星
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int> > g[3300000];//相当于一个二维数组
//vector存图
int u,v,z;
int n,m,flag;
void add(int u,int v,int z){//void类型
g[u].push_back(make_pair(v,z));//制造一个pair,后插法
}
int main(){
scanf("%d%d%d",&n,&m,&flag);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&z);
add(u,v,z);
if(flag==0){
add(v,u,z);
}
}
for(int i=1;i<=n;i++){
if(g[i].size()==0){
printf("\n");//无出边,单独输出一个空行
}
else{
for(int j=int(g[i].size())-1;j>=0;j--){//因为后插,想要升序,就要倒序遍历
printf("%d %d %d\n",i,g[i][j].first,g[i][j].second);
}
}
}
return 0;
}
树(sum变形)
#include<bits/stdc++.h>
using namespace std;
vector<int> g[210000];
int n,s;
int u,v;
long long ans;
map<int,int> mp;//用ma当桶数组
int a[210000],sum[210000];
void add(int u,int v){
g[u].push_back(v);
}
void dfs(int f,int fa){
sum[f]=sum[fa]+a[f];
ans+=mp[sum[f]-s];//符合要求的区间数量
mp[sum[f]]++;
for(int v:g[f]){//用一个变量v遍历vector
if(v==fa){
continue;
}
dfs(v,f);
}
mp[sum[f]]--;//回溯掉之前路径的区间数量
}
int main(){
scanf("%d%d",&n,&s);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
mp[0]=1;
//sum[r]-sum[l-1]=s
//sum[r]-sum[l]=s (0<=l<=r)
//sum[r]-s=sum[l] (有几个sum[l]就有几个符合要求的区间)
//l=0时也有一个符合要求的区间
dfs(1,1);
printf("%lld",ans);
return 0;
}
Tree Cutting
//树的重心:删掉重心后最大的连通块最小
#include<bits/stdc++.h>
using namespace std;
vector<int> g[21000];
int n,x,y,maxson[21000],s[21000];
void add(int u,int v){
g[u].push_back(v);
}
void dfs(int f,int fa){
s[f]=1;
for(int v:g[f]){
if(v==fa){
continue;
}
dfs(v,f);
s[f]+=s[v];
maxson[f]=max(maxson[f],s[v]);
}
maxson[f]=max(maxson[f],n-s[f]);//无根树,上下两个部分都有可能是子树
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x>>y;
add(x,y);//=无根树,双向建边
add(y,x);
}
dfs(1,1);
for(int i=1;i<=n;i++){
if(maxson[i]<=n/2){
cout<<i<<"\n";
}
}
return 0;
}