ATM and Students-(线段树+二分+双指针)

F

题意:
就是给你一个n长度的数组,和本金m,然后在这个数组中找出最长的一段连续区间,在这段区间中当前的权值加上本金m没有<0的时候,求最长的区间。

思考:
看到这题的时候已经没有几分钟了,一看题意很简单,就是求最长的,赶紧想了想,这不就是双指针吗,但是调了调没调出来,又去想二分了,对于每个i点枚举它的最远点,但是这是错误的,这只能保证最远点当前的值是正的,但是中间可能会出现负值,所以这样不行。那该怎么做呢,其实用线段树维护前缀和数组的最小值,这样每次查询最远点的时候,就求这段区间的最小值是多少,如果最小值都满足条件,那么这个区间就满足条件。当然双指针是很简单的,就是如果可以的话就让r++,然后不能加就出来,更新最大值,然后l++。

代码:

线段树版本:

struct Node{
	int L,R;
	int sum;
}t[4*N];

int T,n,m;
int va[N];

void build(int node,int l,int r)
{
	t[node].L = l,t[node].R = r;
	if(l==r)
	{
		t[node].sum = va[l];
		return ;
	}
	int mid = l+r>>1;
	build(node_l,l,mid);
	build(node_r,mid+1,r);
	t[node].sum = min(t[node_l].sum,t[node_r].sum);
}

int query(int node,int l,int r)
{
	if(t[node].L>r||t[node].R<l) return inf;
	if(t[node].L>=l&&t[node].R<=r) return t[node].sum;
	return min(query(node_l,l,r),query(node_r,l,r));
}

bool check(int l,int r)
{
	int res = query(1,l,r)-va[l-1]; //由于维护的是前缀和,求出来之后要减去之前的。
	if(res+m>=0) return true;
	else return false;
}

signed main()
{
	IOS;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		for(int i=1;i<=n;i++)
		{
			int x;
			cin>>x;
			va[i] = va[i-1]+x;
		}
		build(1,1,n);
		int maxn = 0,vall = 0,valr = 0;
		for(int i=1;i<=n;i++)
		{
			int l = i,r = n;
			while(l<r)
			{
				int mid = (l+r+1)>>1;
				if(check(i,mid)) l = mid;
				else r = mid-1;
			}
			if(maxn<l-i+1&&check(i,l)) //注意这里,maxn<l-i+1,该是多少就多少,别l-i
			{
				maxn = l-i+1;
				vall = i,valr = l;
			}	
		}
		if(vall==0||valr==0) cout<<-1<<"\n";
		else cout<<vall<<" "<<valr<<"\n";
	}
	return 0;
}

双指针版本:

int T,n,m;
int va[N];
int dp[N];
 
signed main()
{
	IOS;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		for(int i=1;i<=n;i++) cin>>va[i];
		int now = 0,maxn = 0,l = 1,r = 1,vall = 0,valr = 0;
		while(l<=n&&r<=n)
		{
			while(m+now+va[r]>=0&&r<=n) now += va[r++]; //如果可以r++
			if(maxn<r-l) //更新
			{
				maxn = r-l;
				vall = l,valr = r-1;
			}
			now -= va[l++]; //l++
		}
		if(vall==0&&valr==0) cout<<"-1\n";
		else cout<<vall<<" "<<valr<<"\n";
	}
}

总结:
怎么说呢,对双指针要加强练习和理解,知道该干什么,该怎么做。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的ATM柜员机模拟程序的Java代码示例,包括连接MySQL数据库和GUI界面的实现。这里使用了Java Swing框架实现GUI界面,以及JDBC驱动连接MySQL数据库。 代码中的数据库名为"atm",包含两个表:"account"和"transaction"。"account"表包含账户信息,包括账户号码、密码、余额等字段,"transaction"表包含交易记录,包括交易时间、账户号码、交易类型、交易金额等字段。 注意:以下代码仅供参考,具体实现需要根据实际需求进行修改和完善。 ```java import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.sql.*; public class ATM extends JFrame implements ActionListener { // GUI components private JLabel accountLabel, passwordLabel, balanceLabel; private JTextField accountField; private JPasswordField passwordField; private JButton loginButton, depositButton, withdrawButton, transferButton; private JPanel mainPanel, buttonPanel; // database connection private Connection conn; private Statement stmt; // current user account info private String currentUser; private double currentBalance; public ATM() { // initialize GUI components accountLabel = new JLabel("Account:"); passwordLabel = new JLabel("Password:"); balanceLabel = new JLabel("Balance: $0.00"); accountField = new JTextField(10); passwordField = new JPasswordField(10); loginButton = new JButton("Login"); depositButton = new JButton("Deposit"); withdrawButton = new JButton("Withdraw"); transferButton = new JButton("Transfer"); mainPanel = new JPanel(new GridLayout(3, 2)); buttonPanel = new JPanel(new GridLayout(1, 4)); // add GUI components to main panel mainPanel.add(accountLabel); mainPanel.add(accountField); mainPanel.add(passwordLabel); mainPanel.add(passwordField); mainPanel.add(balanceLabel); mainPanel.add(new JLabel()); // placeholder // add GUI components to button panel buttonPanel.add(loginButton); buttonPanel.add(depositButton); buttonPanel.add(withdrawButton); buttonPanel.add(transferButton); // add action listeners to buttons loginButton.addActionListener(this); depositButton.addActionListener(this); withdrawButton.addActionListener(this); transferButton.addActionListener(this); // add panels to frame add(mainPanel, BorderLayout.CENTER); add(buttonPanel, BorderLayout.SOUTH); // set frame properties setTitle("ATM"); setSize(300, 150); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); // connect to database try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost/atm", "root", ""); stmt = conn.createStatement(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(this, "Failed to connect to database."); } } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == loginButton) { // login button pressed String account = accountField.getText(); String password = new String(passwordField.getPassword()); try { // check if account and password are valid ResultSet rs = stmt.executeQuery("SELECT * FROM account WHERE account_no = '" + account + "' AND password = '" + password + "'"); if (rs.next()) { // login successful currentUser = account; currentBalance = rs.getDouble("balance"); balanceLabel.setText("Balance: $" + String.format("%.2f", currentBalance)); } else { // login failed JOptionPane.showMessageDialog(this, "Invalid account or password."); } rs.close(); } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(this, "Failed to retrieve account information."); } } else if (e.getSource() == depositButton) { // deposit button pressed if (currentUser == null) { // not logged in JOptionPane.showMessageDialog(this, "Please log in first."); return; } String input = JOptionPane.showInputDialog(this, "Enter deposit amount:"); if (input == null || input.isEmpty()) { // cancel button pressed return; } try { double amount = Double.parseDouble(input); if (amount <= 0) { // invalid input JOptionPane.showMessageDialog(this, "Invalid amount."); } else { // update account balance and transaction record currentBalance += amount; stmt.executeUpdate("UPDATE account SET balance = " + currentBalance + " WHERE account_no = '" + currentUser + "'"); stmt.executeUpdate("INSERT INTO transaction (account_no, type, amount) VALUES ('" + currentUser + "', 'Deposit', " + amount + ")"); balanceLabel.setText("Balance: $" + String.format("%.2f", currentBalance)); JOptionPane.showMessageDialog(this, "Deposit successful."); } } catch (NumberFormatException ex) { // invalid input JOptionPane.showMessageDialog(this, "Invalid amount."); } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(this, "Failed to update account information."); } } else if (e.getSource() == withdrawButton) { // withdraw button pressed if (currentUser == null) { // not logged in JOptionPane.showMessageDialog(this, "Please log in first."); return; } String input = JOptionPane.showInputDialog(this, "Enter withdrawal amount:"); if (input == null || input.isEmpty()) { // cancel button pressed return; } try { double amount = Double.parseDouble(input); if (amount <= 0 || amount > currentBalance) { // invalid input JOptionPane.showMessageDialog(this, "Invalid amount."); } else { // update account balance and transaction record currentBalance -= amount; stmt.executeUpdate("UPDATE account SET balance = " + currentBalance + " WHERE account_no = '" + currentUser + "'"); stmt.executeUpdate("INSERT INTO transaction (account_no, type, amount) VALUES ('" + currentUser + "', 'Withdrawal', " + amount + ")"); balanceLabel.setText("Balance: $" + String.format("%.2f", currentBalance)); JOptionPane.showMessageDialog(this, "Withdrawal successful."); } } catch (NumberFormatException ex) { // invalid input JOptionPane.showMessageDialog(this, "Invalid amount."); } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(this, "Failed to update account information."); } } else if (e.getSource() == transferButton) { // transfer button pressed if (currentUser == null) { // not logged in JOptionPane.showMessageDialog(this, "Please log in first."); return; } String input = JOptionPane.showInputDialog(this, "Enter transfer amount:"); if (input == null || input.isEmpty()) { // cancel button pressed return; } try { double amount = Double.parseDouble(input); if (amount <= 0 || amount > currentBalance) { // invalid input JOptionPane.showMessageDialog(this, "Invalid amount."); } else { String targetAccount = JOptionPane.showInputDialog(this, "Enter target account number:"); if (targetAccount == null || targetAccount.isEmpty()) { // cancel button pressed return; } ResultSet rs = stmt.executeQuery("SELECT * FROM account WHERE account_no = '" + targetAccount + "'"); if (rs.next()) { // target account exists double targetBalance = rs.getDouble("balance"); targetBalance += amount; currentBalance -= amount; stmt.executeUpdate("UPDATE account SET balance = " + currentBalance + " WHERE account_no = '" + currentUser + "'"); stmt.executeUpdate("UPDATE account SET balance = " + targetBalance + " WHERE account_no = '" + targetAccount + "'"); stmt.executeUpdate("INSERT INTO transaction (account_no, type, amount) VALUES ('" + currentUser + "', 'Transfer', " + amount + ")"); stmt.executeUpdate("INSERT INTO transaction (account_no, type, amount) VALUES ('" + targetAccount + "', 'Transfer', " + amount + ")"); balanceLabel.setText("Balance: $" + String.format("%.2f", currentBalance)); JOptionPane.showMessageDialog(this, "Transfer successful."); } else { // target account not found JOptionPane.showMessageDialog(this, "Target account not found."); } rs.close(); } } catch (NumberFormatException ex) { // invalid input JOptionPane.showMessageDialog(this, "Invalid amount."); } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(this, "Failed to update account information."); } } } public static void main(String[] args) { new ATM(); } } ``` 希望以上代码对您有所帮助。如有任何疑问或需求,请随时与我交流。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值